FreeRTOS当中的Mail Queue使用教程(CMSIS_v1)
为什么要使用Mail Queue以蜂鸣器举例为什么要用邮箱而不是直接 BeepOn()避免阻塞调用者蜂鸣器响需要时间如果每个调用方自己去响蜂鸣器它们都会被这个延时卡住。现在改成邮箱后调用方发完请求就能继续干别的。统一串行处理多个请求如果多个任务同时想蜂鸣器发声邮箱会把这些请求排队蜂鸣器任务按顺序处理不会互相打架。线程安全、职责清晰硬件操作只放在一个任务里做其他任务只负责发消息结构更稳后续好维护。让蜂鸣器请求变成一个异步队列避免阻塞其他任务并把硬件控制集中到一个地方。什么是Mail QueueFreeRTOS当中传统的Mailbox对队列Queue的一种特殊用法Mailbox QueueQueue length 1特点只能存 1 条消息新消息会覆盖旧消息CMSIS_v1当中的Mail Queue多消息缓存队列带内存管理的消息传递机制CMSIS Mail Queue Queue Memory Pool内部结构[ 内存池 ] → 存放多个 BeepMsg_t↓[ 队列 ] → 存放指针指向这些消息接口函数CMSIS_v1以下我均以蜂鸣器使用举例子初始化接口osMailQId — 句柄/IDosMailQId BeepMail;osMailQDef — 定义邮箱// 定义蜂鸣器消息队列队列长度为10消息类型为BeepMsg_tosMailQDef(BeepMail,BEEP_MSG_QUENE_SIZE,BeepMsg_t);osMailCreate — 创建邮箱// 创建邮箱队列供外部调用接口使用BeepMailosMailCreate(osMailQ(BeepMail),NULL);外部调用接口osMailAlloc — 申请内存// 从邮箱申请一个消息块失败则直接丢弃本次请求posMailAlloc(BeepMail,0);osMailPut — 消息投递// 将消息投递给蜂鸣器任务由任务统一控制 IO 输出osMailPut(BeepMail,p);Task内部处理接口osMailGet — 阻塞等待// 阻塞等待蜂鸣器控制消息evtosMailGet(BeepMail,osWaitForever);osMailFree — 释放内存// 释放消息块osMailFree(BeepMail,p);整体工程—beep.cosThreadId BeepTaskHandle;osMailQId BeepMail;// 定义蜂鸣器消息队列队列长度为10消息类型为BeepMsg_tosMailQDef(BeepMail,BEEP_MSG_QUENE_SIZE,BeepMsg_t);// 外部调用蜂鸣器voidBeep(uint8_tsound,uint8_ttime){BeepMsg_t*p;// 从邮箱申请一个消息块失败则直接丢弃本次请求posMailAlloc(BeepMail,0);if(p!NULL){p-soundsound;p-timetime;// 将消息投递给蜂鸣器任务由任务统一控制 IO 输出osMailPut(BeepMail,p);}}// 蜂鸣器任务入口staticvoidBeepTaskEntry(voidconst*argument){osEvent evt;BeepMsg_t*p;// 包含sound和time/* Infinite loop */// 任务启动时先关闭蜂鸣器避免上电瞬间误响BeepOff();for(;;){// 阻塞等待蜂鸣器控制消息evtosMailGet(BeepMail,osWaitForever);if(evt.statusosEventMail){pevt.value.p;// 打开对应音色保持指定时间后关闭BeepOn(p-sound);osDelay(p-time);osMailFree(BeepMail,p);// 释放消息块BeepOff();}}}// 定义蜂鸣器任务osThreadDef(BeepTask,BeepTaskEntry,osPriorityAboveNormal,0,128);// 创建蜂鸣器任务及其邮箱队列voidBeepTaskInit(void){// 创建邮箱队列供外部调用接口使用BeepMailosMailCreate(osMailQ(BeepMail),NULL);// 创建蜂鸣器任务BeepTaskHandleosThreadCreate(osThread(BeepTask),NULL);}