读者*石 三*问:博主可以介绍下在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); } }}
以上两种方法是常用的,希望大家都掌握一下。 上述仅让大家掌握原理,代码不宜直接复制粘贴使用。
全部0条评论
快来发表一下你的评论吧 !