FreeRTOS内部机制(二)
文章目录FreeRTOS内部机制二3.队列(Queue)3.1队列的核心关中断、环形缓冲区、链表3.1.1怎么互斥访问数据3.1.2 怎么传递数据3.1.3 怎么休眠/唤醒3.2操作示例3.2.1创建队列3.2.2读队列3.2.3写队列4.信号量(semaphore)4.1优先级反转5. 互斥量(mutex)5.1优先级继承6. 事件组(event group)6.1事件组核心关调度器、位操作、链表6.1.1 怎么互斥访问数据6.1.2 位操作6.1.3 链表FreeRTOS内部机制二3.队列(Queue)3.1队列的核心关中断、环形缓冲区、链表3.1.1怎么互斥访问数据简单粗暴关中断3.1.2 怎么传递数据使用环形缓冲区注意pcTail指向队列存储区域的最后一个字节的下一个字节3.1.3 怎么休眠/唤醒有两个链表写队列不成功而挂起读队列不成功而挂起3.2操作示例3.2.1创建队列创建流程xQueueGenericCreate/*1.计算环形缓冲区大小*/xQueueSizeInBytes(size_t)(uxQueueLength*uxItemSize);/*2.申请空间环形缓冲区大小sizeof(Queue_t)*/pxNewQueue(Queue_t*)pvPortMalloc(sizeof(Queue_t)xQueueSizeInBytes);-prvInitialiseNewQueue/*初始化队列成员*/pxNewQueue-pcHead(int8_t*)pucQueueStorage;pxNewQueue-uxLengthuxQueueLength;...图示问为什么pcReadFrom指向最后一个元素答在xQueueReceive()函数中pcReadFrom先向后移如果出界再回绕最后读prvCopyDataFromQueue-prvCopyDataFromQueue pxQueue-u.pcReadFrompxQueue-uxItemSize;//先移动if(pxQueue-u.pcReadFrompxQueue-pcTail){pxQueue-u.pcReadFrompxQueue-pcHead;}3.2.2读队列读队列基本流程taskENTER_CRITICAL();//关中断/*环形缓冲区内有数据*/if(uxMessagesWaiting(UBaseType_t)0){/*拷贝数据*/prvCopyDataFromQueue(pxQueue,pvBuffer);/*有效数据个数减1*/pxQueue-uxMessagesWaitinguxMessagesWaiting-(UBaseType_t)1;/*唤醒向队列发送数据的任务*/xTaskRemoveFromEventList((pxQueue-xTasksWaitingToSend));/*开中断并返回成功*/taskEXIT_CRITICAL();returnpdPASS;}/*环形缓冲区内没数据*/else{/*不愿意等待直接返回*/if(xTicksToWait(TickType_t)0){returnerrQUEUE_EMPTY;}/*愿意等待将自己挂入等待发送链表然后休眠*/else{vTaskPlaceOnEventList((pxQueue-xTasksWaitingToReceive),xTicksToWait);portYIELD_WITHIN_API();}}3.2.3写队列写队列基本流程与读队列基本流程大致相似我们在此不做过多赘述而是讨论如下问题一个任务写队列时如果队列已经满了它会被挂起何时被唤醒超时任务写队列不成功时它会被挂起从ready list移到delayed list中在delayed list中按照超时时间排序系统Tick中断不断发生在Tick中断里判断delayed list中的任务时间到没时间到后就唤醒它别的任务读队列:4.信号量(semaphore)信号量就是特殊的队列队列里使用环形缓冲区存放数据信号量里只记录计数值4.1优先级反转我们假设一个场景现在有三个任务分别是TaskA, TaskB, TaskC他们的优先级情况是Priority APriorityBPriorityCTaskA与TaskC需要用到信号量而TaskB却不需要因为某种原因Task C最先运行,当TaskA准备就绪时因为它无法获取信号量便阻塞在那里此时TaskB也准备就绪因为TaskB的优先级大于TaskC, 所以TaskB开始运行。此时就出现了优先级反转的情况—中等优先级的任务反而先运行完最高优先级的任务无法得到实时性保障这违反了“高优先级任务应优先于低优先级任务执行”的实时性原则5. 互斥量(mutex)互斥量就是特殊的队列互斥量更是特殊的信号量互斥量实现了优先级继承5.1优先级继承互斥量实现了优先级继承解决了信号量优先级翻转的问题优先级继承 (Priority Inheritance)是实时操作系统RTOS中解决优先级反转问题的核心算法机制当高优先级任务试图获取一个被低优先级任务持有的互斥量Mutex时内核会临时提升低优先级任务的优先级使其与等待该锁的最高优先级任务相同目的防止中等优先级任务抢占低优先级任务从而让低优先级任务能尽快执行完临界区代码、释放锁最终让高优先级任务尽早运行在下列的图示中L任务代表低优先级任务、M任务代表中优先级任务、H任务代表高优先级任务6. 事件组(event group)学校组织秋游组长在等待张三我到了李四我到了王五我到了组长说好大家都到齐了出发秋游回来第二天就要提交一篇心得报告组长在焦急等待张三、李四、王五谁先写好就交谁的在这个日常生活场景中出发要等待这3个人都到齐他们是与的关系交报告只需等待这3人中的任何一个他们是或的关系在FreeRTOS中可以使用事件组(event group)来解决这些问题6.1事件组核心关调度器、位操作、链表6.1.1 怎么互斥访问数据简单粗暴关调度器问为什么在队列、信号量和互斥量中是关中断而事件组是关调度器先说结论在xEventGroupSetBitsFromISR()函数中并不会直接设置标志位而是写队列唤醒一个“守护任务”该任务读到数据后会写标志位因此标志位是在任务中被设置的所以只需要关闭调度器下面我们在源码中进行证明6.1.2 位操作设置位等待位6.1.3 链表设置位后会唤醒所有符合条件的任务等待位的时候条件不满足则会休眠
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2424243.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!