代码之家  ›  专栏  ›  技术社区  ›  Nima Azad

在带有STM32的FreeRTOS中,在三个相同优先级的任务中使用一个UART

  •  0
  • Nima Azad  · 技术社区  · 1 年前

    我试图在三个相同优先级的任务中使用一个UART,如下面的代码,但发生的事情让我感到困惑!事实上,我希望任何任务每秒发送一次字符串,所以我应该每秒在终端中有3个语句,但UART传输函数只工作一次,其他2个传输函数被省略了。

    当我将任务优先级更改为高、正常和低时,效果很好。如何在不更改任务优先级的情况下解决此问题?

    事实上,我不想有一个复杂的RTOS程序。我只想要一个没有信号量或互斥的简单多任务程序!我希望这是可能的,因为我不想给我的程序增加复杂性。(请注意,如果我添加了等待UART就绪功能,程序工作正常,但这不是微控制器编程中的常见方法)。

      /* Create the thread(s) */
      /* definition and creation of defaultTask */
      osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
      defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
    
      /* definition and creation of myTask02 */
      osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 128);
      myTask02Handle = osThreadCreate(osThread(myTask02), NULL);
    
      /* definition and creation of myTask03 */
      osThreadDef(myTask03, StartTask03, osPriorityNormal, 0, 128);
      myTask03Handle = osThreadCreate(osThread(myTask03), NULL);
    
    void StartDefaultTask(void const * argument)
    {
      /* Infinite loop */
      for(;;)
      {
        //while (HAL_UART_GetState (&huart2) != HAL_UART_STATE_READY);
        HAL_UART_Transmit(&huart2,(uint8_t*)"T1\r\n",sizeof("T1\r\n")-1,100);
        osDelay(1000);
      }
    }
    
    void StartTask02(void const * argument)
    {
      /* Infinite loop */
      for(;;)
      {
        //while (HAL_UART_GetState (&huart2) != HAL_UART_STATE_READY);
        HAL_UART_Transmit(&huart2,(uint8_t*)"T2\r\n",sizeof("T2\r\n")-1,100);
        osDelay(1000);
      }
    }
    
    void StartTask03(void const * argument)
    {
      /* Infinite loop */
      for(;;)
      {
        //while (HAL_UART_GetState (&huart2) != HAL_UART_STATE_READY);
        HAL_UART_Transmit(&huart2,(uint8_t*)"T3\r\n",sizeof("T3\r\n")-1,100);
        osDelay(1000);
      }
    }
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   pmacfarlane    1 年前

    使用互斥体有什么问题?显然,您需要某种方法来防止这三个任务同时访问UART,互斥体是实现这一点的明显方法。

    最简单的方法是将所有UART功能(包括互斥)移动到一个函数中,从而从单个任务中消除这种“复杂性”:

    static StaticSemaphore_t uart_mutex;
    static SemaphoreHandle_t h_uart_mutex = NULL;
    
    void init_mutex(void) // Called before tasks are created
    {
        h_uart_mutex = xSemaphoreCreateMutexStatic ( &uart_mutex );
    }
    
    void send_string(const char *str)
    {
        xSemaphoreTake(h_uart_mutex, ( TickType_t ) 1000);
        HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen(str), 100);
        xSemaphoreGive(h_uart_mutex);
    }
    
    void StartTask02(void const * argument)
    {
      /* Infinite loop */
      for(;;)
      {
        send_string("T2\r\n");
        osDelay(1000);
      }
    }
    

    另一种方法是有一个消息队列,你的任务将字符串输入其中,另一个任务将字符串读出并发送到UART。但在我看来,这甚至更复杂,在内部,它可能无论如何都在使用互斥体来保护队列。

    推荐文章