当使用RTOS进行多任务编程时,同一个硬件(例如UART、I2C等)被多个任务访问的情况比较普遍。如果没有合理处理,就会导致“混乱”的情况。
为了解决这种情况,有多种方法可供选择。下面以FreeRTOS为例,主要介绍两种常见的方法:互斥和队列。
互斥访问硬件资源的方法
互斥量:是一个可以处于两个状态(已解锁和已加锁)的变量。
原理:创建一个互斥量,任务A需要占用资源(例如使用UART发送数据),则该任务将占用该资源(UART)。此时,任务B和其他任务将无法占用该资源。当任务A使用完资源(例如发送完数据)之后,就会释放该资源,其他任务则可以竞争使用该资源。
在FreeRTOS中,可以使用xSemaphoreCreateMutex()函数创建一个互斥量,使用xSemaphoreTake()函数占用资源并设置互斥量为锁定状态,通过xSemaphoreGive()函数将互斥量释放。
创建互斥量
任务A占用资源
使用资源(发送数据)
任务A释放资源
优先级高的任务B占用资源
使用资源
任务B释放资源
依次,优先级任务占用资源
·
·
·
代码:
//创建互斥量资源
SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateMutex();
void TaskA(void *pvParameters)
{
for(;;)
{
//占用资源
if(xSemaphoreTake(xSemaphore, 10 ) == pdTRUE)
{
//使用资源(发送数据)
USART_SendNByte();
//释放资源
xSemaphoreGive(xSemaphore);
}
}
}
信号量与互斥量区别:
信号量:多个任务同步使用某个资源;
一个任务完成某个动作后通过信号告诉别的任务,别的任务才可以执行某些动作;
互斥量:多任务互斥使用某个资源;
一个任务占用某个资源,那么别的任务就无法访问,直到该任务离开,其他任务才可以访问该资源;
队列访问串口的方法
队列操作方法就是FIFO,先入先出的原理。比如:任务A要使用UART发送一串数据,将其加入队列; 接着任务B也要使用UART发送一串数据。
那么,任务A将这串数据加入队列,接着任务B又将要发送的一串数据加入队列。
在另外一个UART发送的任务中,从队列中按照FIFO方式读取队列里面的数据,依次发送出去即可。
创建一个队列(发送数据队列)
创建一个任务(UART发送数据任务)
任务A加入队列
任务B加入队列
·
·
·
另外一边的任务,依次读取队列数据,使用UART发送出去。
代码:
QueueHandle_t xQueue;
xQueue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE);
xTaskCreate(UART_Send_Task, "UART_Send", STACK_SIZE, NULL, TASK_PRIORITY, NULL);
void TaskA(void *pvParameters)
{
for(;;)
{
//任务相关操作
//加入队列
xQueueSend(xQueue, &TaskA_Buf, 10)
}
}
void TaskB(void *pvParameters)
{
for(;;)
{
//任务相关操作
//加入队列
xQueueSend(xQueue, &TaskB_Buf, 10)
}
}
void UART_Send_Task(void *pvParameters)
{
for(;;)
{
//循环读取队列BUF
if(xQueueReceive(xQueue, &Buf, 10) == pdTRUE)
{
USART_SendNByte(&Buf);
}
}
}
以上两种方法比较常用,也比较简单,希望对大家有帮助。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !