满堂花醉三千客,一剑霜寒十四洲。这篇文章主要讲述1265_FreeRTOS中向任务就绪链表增加任务的实现分析相关的知识,希望能为你提供帮助。
全部学习汇总: ??https://github.com/GreyZhang/g_FreeRTOS??
前面分析了如何创建一个task,在task创建的最后调用了两个函数,其中一个是用来实现任务对象的初始化,另一个是把初始化后的任务增加到任务就绪链表。前面的这部分代码已经解读完成,这一次看一下如何把任务增加到任务就绪链表上。
操作的第一步是进入关键代码的临界保护,这一步操作一般是处理一些中断的信息。针对不同平台的中断处理会有很大的差异,这一次正好趁此机会看一下ARM M3内核的MCU上这部分如何处理。
几次跳转后,这个函数的等同效果是这样子的。这里面,又进一步调用了中断的禁用接口。接下来,分析一下这个关中断接口的实现。
上面,是经过了几次封装拆解之后找到的原始的设计。总体的设计应该很简单,第一步实现了一个临时变量的赋值,第二部则是给一个寄存器进行了赋值,赋值的结果就是第一句的处理结果输出出来的临时变量数值。后面,又执行了2条汇编指令。这里,configMAX_SYSCALL_INTERRUPT_PRIORITY的数值展开后为80。
感觉上,第一条质量可以直接用C语言实现。类似的想法,做一个测试先看一下系统是否有异常出现。
做了如上修改之后,针对我之前的工程测试功能依然没发现问题。
至少,现在创建的task中进行打印操作没出现异常。但是这里的参数不能够再减少,不能够直接进行参数的赋值。这里使用了代指的参数,其作用应该就是为了让编译器帮忙分配一个中转的寄存器实现特殊寄存器的赋值。
针对BASEPRI,这里找到了一个说明信息。其实,这个是特殊寄存器里面的exception掩码寄存器中的一个。
这是一个基础优先级掩码寄存器。
这个寄存器数值如果是0的时候是没有效果的,如果是非零的时候,会屏蔽一些中断。这个寄存器定义的其实是exception所处理的最小的优先级,只要优先级在数值上等于等于这个数值exception就不会去处理。
这一条指令,理解应该很容易,它的作用应该是:在这个位置同步一下指令。
这个与上面的指令同步类似:在这个位置同步一下数据。
这样,再回到前面的函数接口。这个接口前面已经分析了禁用中断的实现,其实是屏蔽了一部分优先级的中断处理。而进入这个函数之后,先会对一个计数器进行++操作。这里有一个需要注意的信息,初始时uxCriticalNesting = 0xaaaaaaaa,而不是0。这部分也需要在代码中测试一下运行起来的效果是否跟我分析的一致。如果初始值uxCriticalNesting = 0xaaaaaaaa,那么在初期的任务创建的时候其实只是进行了一个中断的屏蔽。但是,这样是否会影响到初始化时候可以允许的任务创建的数目呢?
先对上面的疑问做一个测试,看看数值究竟是多少。
【1265_FreeRTOS中向任务就绪链表增加任务的实现分析】从上面的结果看,这一次的分析路径是对的。初始化的时候,这里的数值就是一个非零数值。
继续前面的分析,如果当前没有已经就绪的任务,那么新加入的这个任务设置为当前就绪任务。如果就绪的任务数这次是1,说明这是第一次尝试往就绪任务链表中加信息,也需要对就绪任务链表进行初始化。
如果当前就绪的任务已经存在了,那么看看调度器是否已经运行。还没运行的话,高优先级的任务设置为当前就绪任务。
之后,把这个任务加入到任务就绪链表中并退出关键保护。再次看调度是否运行,没有运行的话一切就结束了。如果运行了,根据实际的配置触发一次任务抢占处理。
抢占模式下,上面的任务抢占处理运行的是这一段代码。实现的其实就是一个PendSV的请求,在超级权限模式下触发一次上下文的切换。后面的数据以及指令的同步没有特别的必要性,只是以防万一。
这样,就绪任务链表的增加实现分析基本结束。可能还涉及到一个PendSV的具体分析,这个又涉及到一些内核信息,后面读一下文档后再做分析。
推荐阅读
- Tomcat高负载WEB服务器JVM - 常用分析工具
- Tomcat高负载WEB服务器JVM - VirtualVM
- 单细胞论文记录(part9)--Spatial charting of single-cell transcriptomes in tissues
- IDEA复制方法的全路径
- Tomcat高负载WEB服务器tomcat目录介绍
- #yyds干货盘点# 解决剑指offer(跳台阶扩展问题)
- Eclipse项目环境配置
- Linux - 管道(|)和grep 命令
- MongoDBJMeter压力测试(Java代码)