关注分享主机优惠活动
国内外VPS云服务器

7. FreeRTOS——队列同步与互斥

摘要:本专栏提到了魏东山、野火、正电原子等博主的教程。 如有侵权请告知。 我们将立即删除该帖子并致歉。 个人总结。 如果我做错了什么,请纠正我。

声明:本专栏参考了魏东山、夜火、正点Atom等博主的FreeRTOS教程。 如有侵权请告知。 我们将立即删除该帖子并致歉。 个人总结。 如果我做错了什么,请纠正我。 。 转发:理解同步和互斥链接的概念实验1:同步实验代码重点是创建队列任务句柄。 在此之前,我们需要通过添加队列头文件来创建队列函数。 每个任务处理事件。 实验2:互斥实验代码重点关注

。 转发:了解同步和互斥链接的概念。

实验一:同步

我们来看看如何做一个同步实验

实验代码/** FreeRTOS v9.0.0 + STM32动态任务创建实验平台:魏东山STM32F103ZE Board开发* */ #include "FreeRTOS.h" #include "task.h" #include "queue.h"/ * 开发板硬件bsp头文件 */#include "bsp_led .h"#include "bsp_usart.h" /* Task句柄 */static TaskHandle_t AppTaskCreate_Handle = NULL;static TaskHandle_t Task1_Handle = NULL;static TaskHandle_t Task2_Handle = NULL;static TaskHandle_t Task3_Handle = NULL;static xQueueeHandle MsgQueue; /*队列句柄*//* 函数声明*/static void AppTaskCreate(void);/* 用于创建任务*/static void Flag1_Task(void* pvParameters);/* LED1_Task 任务实现*/static void Flag2_Task ( void* pvParameters );/* LED2_Task 任务实现*/static void Flag3_Task(void* pvParameters);/* LED3_Task 任务实现*/static void BSP_Init(void);/* 用于初始化板载相关资源*//* ** ** ************************************************** *** *** ********* * @brief 主函数* @param None* @retval None* @note 步骤一:开发板硬件初始化 步骤二:APP 创建应用任务 步骤三:启动FreeRTOS,启动多任务调度 ********************************************** ** ** *****************/int main(void){ BaseType_t xReturn = pdPASS;/* 返回创建信息 定义值。 默认为pdPASS */ /* 开发板硬件初始化 */ BSP_Init(); printf("这是一个STM32F103ZE开发板- FreeRTOS -动态创建任务!/r/n"); sizeof(int));/*创建队列:参数、队列长度、每个长度的大小(字节)*/ /* 创建AppTaskCreate 任务*/ xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate, /* 任务入口函数*/ (const char* )"AppTaskCreate",/* 任务名称*/ (uint16_t )512, /* 任务堆栈大小*/ (void* )NULL,/* 任务入口函数参数*/ (UBaseType_t )1, /* 任务优先级*/ (TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针*/ /* 开始任务调度*/ if(pdPASS == xReturn ) vTaskStartScheduler(); /* 启动任务并启用调度*/ 否则返回 -1; while(1); /* 这里一般不执行*/ }/ ************ * ****************************************************** ****** *********** * @函数名称:AppTaskCreate * @函数描述:顺序 为了便于管理,所有任务创建函数都应该放在一个函数内 * @参数:无 * @返回值:无 ** ********************** ****** ************ ******** *****************/英石atic void AppTaskCreate(void){ BaseType_t xReturn = pdPASS;/* 定义创建信息的返回值。 默认为 pdPASS */ taskENTER_CRITICAL(); //进入临界区/* Flag1_Task 创建任务*/ xReturn = xTaskCreate((TaskFunction_t)Flag1_Task , /* 任务输入函数*/ (const char* )"Flag1_Task",/* 任务名称*/ (uint16_t )512, /* 任务堆栈大小*/ (void* )NULL,/* 任务入口函数参数*/ ( UBaseType_t )2, /* 任务优先级*/ (TaskHandle_t* )&Task1_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn) printf("Flag1_Task 任务创建成功!/r/n"); / *创建 Flag2_Task 任务*/ xReturn = xTaskCreate((TaskFunction_t)Flag2_Task , /*任务入口函数*/ ( const char*)"Flag2_Task",/*任务名称*/ (uint16_t)512, /*任务堆栈大小*/(void* )NULL,/* 任务入口函数参数*/ (UBaseType_t )2, /* 任务优先级*/ (TaskHandle_t* )&Task2_Handle);/* 任务控制块指针*/ if(pdPASS == xReturn) printf ( " Flag2_Task任务创建成功!/r/n"); /* 创建Flag3_Task任务*/ xReturn = xTaskCreate((TaskFunction_t )Flag3_Task, /* 任务入口函数*/ (const char* )"Flag3_Task" ,/* 任务名称 */ (uint16_t )512, /* 任务堆栈大小*/ (void* )NULL,/* 任务入口函数参数*/ (UBaseType_t )1, /* 任务优先级*/ (TaskHandle_t* ) &Task3_Handle);/* 任务控制块指针*/ if(pdPASS == xReturn) printf(" Flag3_Task 任务创建成功!/r/n"); //删除AppTaskCreate 任务 taskEXIT_CRITICAL();边界区域}/************************************************ ************ ************************ * @函数名称:LED_Task * @函数描述:LED_Task 任务体****************************************************** ************ * ******/uint8_t flag1;uint8_t flag2;uint8_t flag3;/*优先级2*/static void Flag1_Task(void*参数){static int value,i; while (1) { for(i=10000;i >1;i--) flag1=1; flag2=0; /* 填充队列*/ value++; ! value=%d /r/n", value); void Flag2_Task(void* argument){static int value1; while (1) { /*如果读取队列消息*/if(xQueueReceive(MsgQueue,(void * )&value1,pdFALSE )==pdPASS){ flag1=0; flag3=0; printf("任务 2 正在运行! value=%d/r/n",value1);/*输出读取的值*/} //vTaskDelay(10); /*1个tick延迟*/ }}/*优先级2*/static void Flag3_Task( void*parameter ){static int value2; while (1) { flag1=0; printf("任务3正在运行!value=%d/r/n",value2); /* 1个刻度延迟 * / }}/ ****** ****************************************************** **************** * @ 函数名称:BSP_Init * @ 函数描述:板级外设初始化,板子上的所有初始化都可以放在函数内部 * @ 参数: * @返回值:无************************************************ **** *** * ****************************************/静态无效BSP_Init(无效){/ * * STM32中断优先级 组为4,也就是说用4位来表示抢占优先级,范围是0到15。 * 如果以后还有其他任务需要使用中断,优先级组就只有一次统一使用该优先级组,不再分组 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/* LED 初始化*/LED_GPIO_Config();/* 串口初始化*/USART_Configvoid (); **************************EN。文件 D********************************************/ 亮点

创建三个任务优先级321。

创建队列任务句柄。 在执行此操作之前,您需要添加队列头文件。

创建队列函数。

xQueueCreate();

每个任务处理一个事件

flag1Task flag2Task

flag3Task

根据以上信息,你认为任务执行过程是怎样的?

任务1和任务2都在运行,没有进入阻塞状态。 因为任务3的优先级比任务1和任务2低,所以任务3肯定不会运行。 在这种情况下,任务 3 将不会运行。 如何让任务1和2以相同的优先级运行?

直接模拟以确保串口实际上不混乱。 任务 1 首先运行,然后任务 2 打印信息。 这是因为任务同步是通过队列发送信息来实现的。

请回来尝试一下,看看这些任务是否是互斥的。

实验二:互斥实验代码/** FreeRTOS v9.0.0 + STM32动态任务创建实验平台:魏东山STM32F103ZE开发板**/ #include "FreeRTOS.h"# include "task.h"# include "queue.h"/* 开发板硬件bsp头文件*/#include "bsp_led .h"#include "bsp_usart.h"/* 任务句柄*/static TaskHandle_t AppTaskCreate_Handle = NULL;static TaskHandle_t Task1_Handle = NULL;static TaskHandle_t Task2_Handle = NULL;//静态TaskHandle_t Task3_Handle = NULL;//静态QueueHandle_t xQueueCalcHandle;static QueueHandle_t xQueueUARTcHandle;/* 函数声明*/static void AppTaskCreate(void);/* 用于创建任务*/static void Flag1_Task(void* pvParameters);/* LED1_Task 任务实现*/static void Flag2_Task(void * pvParameters);/* LED2_Task任务实现*///static void Flag3_Task(void* pvParameters);/* LED3_Task任务实现*/static void BSP_Init(void);/* 用于初始化板载相关资源 *//* 创建。 queue * /int InitUARTLock(void){int val;xQueueUARTcHandle = xQueueCreate(1, sizeof(int));/*创建队列*/if (xQueueUARTcHandle == NULL){printf("队列无法创建/r/n" ); return -1;/*创建失败*/}xQueueSend(xQueueUARTcHandle, &val, portMAX_DELAY);/*等待*/return 0;/*创建成功*/ }/*接收队列消息*/void GetUARTLock( void ){ int val;xQueueReceive(xQueueUARTcHandle, &val, portMAX_DELAY);}/*发送队列消息*/void PutUARTLock(void){int val;xQueueSend(xQueueUARTcHandle, &val , portMAX_DELAY);}/********************************************************* * ************ * @brief 主函数* @param None* @retval None* @note 步骤一:初始化开发板硬件 步骤二:创建APP应用任务 步骤三:FreeRTOS启动,开始调度多任务**************************************************** **** **** ** ******************/int main(void){ BaseType_t xReturn = pdPASS;/* 定义创建信息的返回值。 默认为 pdPASS */ /* 开发板硬件初始化 */ BSP_Init(); printf("这是一块 STM32F103ZE 开发板 - FreeRTOS - 动态创建任务!/r/n ");InitUARTLock();/*调用队列创建函数*/ /* AppTaskCreate 创建任务*/ xReturn = xTaskCreate ((TaskFunction_t)AppTaskCreate, /* 任务入口函数*/ (const char* )"AppTaskCreate", /* 任务名称*/ (uint16_t )512, / * 任务堆栈大小*/ (void* ) NULL,/*任务入口函数参数*/ (UBaseType_t)1, /*任务优先级*/(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */ /* 开始调度任务*/ if(pdPASS == xReturn) vTaskStartScheduler(); /* 启动任务并启用调度 */ 否则返回 - 1; 而 (1); /* 通常不在这里执行*/ }/************************************ * *** ********************************** * @函数名称:AppTaskCreate * @函数描述:For方便,管理,一切将任务创建功能放在这个函数里面 * @Parameters: None * @Return value: None **************** ************ ** ****** ********************************************** **/static void AppTaskCreate(void ) { BaseType_t xReturn = pdPASS;/* 定义创建信息的返回值。 默认为 pdPASS */ taskENTER_CRITICAL() //进入临界区/* 创建 Flag1_Task 任务*/ xReturn = xTaskCreate((TaskFunction_t)Flag1_Task, /* 任务入口函数 */ (const char* ) "Flag1_Task", /* 任务名称*/ (uint16_t ) 512, /* 任务堆栈大小 */(void* )NULL,/* 任务入口函数参数*/ (UBaseType_t )2, /* 任务优先级*/ (TaskHandle_t* )&Task1_Handle);/* 任务控制块指针*/ if(pdPASS == xReturn) printf ( " Flag1_Task任务创建成功!/r/n"); /* 创建Flag2_Task任务*/ xReturn = xTaskCreate((TaskFunction_t )Flag2_Task, /* 任务入口函数*/ (const char* )"Flag2_Task" ,/* 任务名称 */ (uint16_t )512, /* 任务堆栈大小 */ (void* )NULL,/* 任务入口函数参数 */ (UBaseType_t )2, /* 任务优先级 */ (TaskHandle_t* ) &Task2_Handle);/* 任务控制块指针*/ if(pdPASS == xReturn) printf(" Flag2_Task 任务创建成功!/r/n"); /* 创建 Flag3_Task 任务 */// xReturn = xTaskCreate((TaskFunction_t)Flag3_Task, /* 任务入口函数*// /(const char* )"Flag3_Task",/* 任务名称*/// (uint16_t )512, /* 任务堆栈大小*/// (void* )NULL,/* 任务入口函数参数*/// (UBaseType_t ) 1, /* 任务优先级 */// (TaskHandle_t* )&Task3_Handle);/* 任务控制块指针 */// if (pdPASS == xReturn)// printf("Flag3_Task 任务创建成功!/r/n ") ; vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务 taskEXIT_CRITICAL(); //退出临界区 }/**************** *********** ************** ************************************** *** * @函数名称:LED_Task * @函数描述:LED_Task 任务体 **** ***************************** *** ****************** ********** **************/uint8_t 标志1;uint8_t flag2;uint8_t flag3;/*优先级2*/static void Flag1_Task(void* Parameter ){ while (1) {GetUARTLock(); /*调用消息接收函数获取使用权*/ printf("Task1 Running!/r/n");PutUARTLock();/*调用消息发送函数释放使用权*/ vTaskDelay(1); /*延迟1个tick*/ }}/*优先级2*/static void Flag2_Task( void*参数){ while (1) { GetUARTLock();/*调用消息接收函数获取使用权*/printf("Task2 Running!/r/n");PutUARTLock();/*消息发送函数释放使用权right*/ vTaskDelay(1); /* 延迟1个tick */ }}/*优先级1*///static void Flag3_Task(void*parameter)//{//static int value2;// while (1)// {// flag1=0;// flag2=0;//flag3=1;// printf("任务3正在运行!value=%d/r/n",value2);// vTaskDelay(10) ); 1 个刻度延迟 */ // // }//}/**************************************** ****** * * ********************************************** ****** * @函数名称:BSP_Init * @函数描述:板级外设初始化,板上所有初始化都可以放在该函数中 * @参数:* @返回值:无 ****** ****************************************************** ****************** *****/静态void BSP_Init(void){/* *STM32中断优先级组为4。 即用4个比特来指示抢占优先级。 范围是 0-15 * 优先级分组只能分组一次。 如果以后还有其他任务需要使用中断,就一刀切使用*。 此优先级分组不应重新分组。 */NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );/* LED初始化*/LED_GPIO_Config();/* 串口初始化*/USART_Config(); }/******************** ** * *************文件结束************ ******************/ 亮点

实验中创建了两个任务,任务优先级相同为2

在危急保护等任务处理事件中创建这些功能。 首先调用接收消息的函数获取使用权限,然后调用发送消息的函数。 消息功能释放使用权限。 (队列有数据表明其他人可以读取队列)

模拟看看你实验的效果

Git仓库源码地址:https://gitee.com/他-dejian /free-rtos.git

未经允许不得转载:主机频道 » 7. FreeRTOS——队列同步与互斥

评论 抢沙发

评论前必须登录!