RTOS多线程访问同一硬件(如UART)的方法

描述

读者*石 三*问:博主可以介绍下在RTOS下多个任务访问同一硬件的方法吗?比如说,多个任务都要用到串口打印信息。

我的回答是:使用互斥量、队列两种方式都能解决访问冲突的问题。

多线程访问同一串行硬件在许多系统中经常使用,如多个线程都使用UART收发数据、多个线程使用读写SPI_FLASH、I2C_E2PROM,CAN总线收发数据等······

如果每个线程都同时抢占同一串口去读写操作,那么很容易出现问题。为了解决其中的冲突问题,就需要使用一定的办法。下面以UART为例,基于FreeRTOS讲述一下基本的互斥量和队列方式的解决方法。

Ⅰ互斥访问方法

互斥量:是一个可以处于两态之一的变量:解锁和加锁。

原理:创建一个互斥量,线程A在需要占用资源(使用UART发送数据),把资源(UART)占用。此时,线程B及其他线程就不能占用该资源。当线程A使用完资源(UART发送完数据),释放资源,其他线程就可以抢占该资源。

创建互斥量

线程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);    }  }}

以上两种方法是常用的,希望大家都掌握一下。 上述仅让大家掌握原理,代码不宜直接复制粘贴使用。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
评论(0)
发评论
willan 2023-04-19
0 回复 举报
信号量表示资源数,信号才是软中断 收起回复

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分