我尝试在三个相同优先级的任务中使用一个 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);
}
}
使用互斥体有什么问题?显然,您需要某种方法来防止三个任务同时访问 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。但在我看来,这更加复杂,并且在内部它可能无论如何都使用互斥体来保护队列。