2

我正在使用 STM32F1 (STM32F103C8T6) 来开发使用 FreeRTOS 的项目。

以下是我的GPIO和USART1接口配置:

    __GPIOA_CLK_ENABLE();
    __USART1_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;//115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  HAL_UART_Init(&huart1);

  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);

问题是:为什么UART传输在线程启动之前工作,但在线程启动后或从线程开始?我想从线程传输数据。IE

int main(void)
{
     Initializations();

     //THIS WORKS!!
     uart_transmit_buffer[0] = 'H';
     uart_transmit_buffer[1] = 'R';
     uart_transmit_buffer[2] = '#';
     uint8_t nums_in_tr_buf = 0;
     nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t);
     state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000);

     StartAllThreads();
     osKernelStart();

     for (;;);
}

static void A_Random_Thread(void const *argument)
{
      for(;;)
      {
         if (conditionsMet())  //Executed once when a proper response received.
         {
            //BUT NOT THIS :(!!
            uart_transmit_buffer[0] = 'H';
            uart_transmit_buffer[1] = 'R';
            uart_transmit_buffer[2] = '#';
            uint8_t nums_in_tr_buf = 0;
            nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t);
            state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000);
        }
      }
}

我确保没有线程处于死锁状态。问题是 UART_HAL_Transmit 给出了 HAL_BUSY 状态。

此外,我有一个线程专门用于接收和解析来自 UART RX 的信息,我怀疑这可能是问题的原因。以下是代码:

static void UART_Receive_Thread(void const *argument)
{
  uint32_t count;
  (void) argument;
    int j = 0, word_length = 0;

  for (;;)
  {
            if (uart_line_ready == 0)
            {
                    HAL_UART_Receive(&huart1, uart_receive_buffer, UART_RX_BUFFER_SIZE, 0xFFFF);
                    if (uart_receive_buffer[0] != 0)
                    {
                            if (uart_receive_buffer[0] != END_OF_WORD_CHAR)
                            {
                                    uart_line_buffer[k] = uart_receive_buffer[0];
                                    uart_receive_buffer[0] = 0;
                                    k++;
                            }
                            else
                            {
                                    uart_receive_buffer[0] = 0;
                                    uart_line_ready = 1;
                                    word_length = k;
                                    k = 0;
                            }
                    }
            }
            if (uart_line_ready == 1)
            {
                    //osThreadSuspend(OLEDThreadHandle);
                    for (j = 0; j <= word_length; j++)
                    {
                            UART_RECEIVED_COMMAND[j] = uart_line_buffer[j];
                    }
                    for (j = 0; j <= word_length; j++)
                    {
                            uart_line_buffer[j] = 0;
                    }
                    uart_line_ready = 0;

                    RECEIVED_COMMAND = ParseReceivedCommand(UART_RECEIVED_COMMAND);
                    if (RECEIVED_COMMAND != _ID_)
                    {
                            AssignReceivedData (word_length);  //Results in uint8_t * RECEIVED_DATA
                    }
                    //osThreadResume(OLEDThreadHandle);
            }
          //Should be no delay in order not to miss any data..
  }
}

我怀疑问题的另一个原因可能与系统中断有关(另请注意初始化部分,我配置了 NVIC):

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
}

对此问题的任何帮助或指导将不胜感激。提前致谢。

4

3 回答 3

2

据我HAL_UART_Transmit所知,如果不是__HAL_LOCK(huart). RX 线程会锁定句柄,然后 TX 线程也会尝试锁定并返回 HAL_BUSY。HAL_UART_Transmit_IT并且HAL_UART_Receive_IT在发送/接收期间不要锁定手柄。

这可能会导致State成员出现问题,因为它是由辅助函数UART_Receive_ITUART_Transmit_IT. 虽然我认为这不会影响操作。

您可以修改该功能以允许同时进行 RX 和 TX。每次他们发布新版本的 HAL 时,您都必须更新它。

问题是 ST HAL 不适合与 RTOS 一起使用。它在宏的定义中这么说__HAL_LOCK。重新定义它以使用 RTOS 的互斥锁可能也值得尝试。与HAL_Delay()使用 RTOS 的线程睡眠功能相同。

一般来说,通过线程中的阻塞函数发送应该没问题,但我不会使用线程中的阻塞函数接收数据。您一定会以这种方式遇到溢出错误。

同样,如果您在接收中断中进行过多处理,您也可能会遇到溢出错误。我更喜欢使用 DMA 进行接收,如果我的 DMA 流用完,则使用中断。中断只将数据复制到缓冲区,类似于 DMA。然后使用一个processRxData线程来处理实际数据。

于 2017-04-26T08:42:25.127 回答
1

使用 FreeRTOS 时,您必须将中断优先级设置为 5 或更高,因为低于 5 是为操作系统保留的。因此,更改您的代码以将优先级设置为:

HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
于 2017-04-11T08:47:03.857 回答
1

这个问题原来与阻塞语句有关。由于 UART_Receive_Thread 内部有 HAL_UART_Receive 并且会阻塞线程直到收到某些内容,这会导致 HAL 繁忙(因此,HAL_BUSY 状态)。

解决方案是使用非阻塞语句而不更改任何其他内容。即同时使用HAL_UART_Receive_ITHAL_UART_Transmit_IT并忽略阻塞语句有效。

感谢所有导致此解决方案的建议。

于 2017-04-11T20:03:23.780 回答