1.Ports/os_cpu_c.h
(1)写明了三种实现临界区的方式及其特点
第一种:简单的禁止中断/打开中断指令。好处是实现简单,坏处是退出临界区后中断肯定是被打开的,不管原来进入临界区之前是关的还是开的。没有实现
第二种:在进入临界区之前会保存中断状态,然后在退出临界区时会恢复原来的状态。简单说:就是原来是开的临界区后还是开,原来是关的临界区后还是关。没有实现
第三种:在要使用临界区的函数中定义一个局部变量名叫cpu_sr,然后在进入临界区前将CPSR保存到cpu_sr中,然后在退出临界区时将cpu_sr恢复到CPU的CPSR中,以此来实现临界区中断状态保存和回复。
(2)栈有四种:满减栈、满增栈、空减栈、空增栈
满栈:栈指针SP始终指向栈中最后一个元素,当我们要再次入栈时要先移动SP再放入。出栈时直接先出栈一个元素然后SP再移动。
空栈:栈指针SP时钟指向栈中最后一个元素后面的第一个空位,入栈时直接入栈然后SP再去移动。出栈时要先移动SP再去出栈。
增栈:栈底在低内存地址处,入栈时栈指针SP向内存地址较大的方向走
减栈:栈底在高内存地址处,入栈时栈指针SP向内存地址较小的方向走
ARM的ATPCS中规定,ARM应该用满减栈。但是可以确定,你实际中遇到的ARM的平台都是满减栈。
(3)OS_TASK_SW,OS代表操作系统,TASK翻译为任务(uCOS中任务就相当于linux windwos中的进程、线程等概念),SW是switch,切换。OS_TASK_SW就是OS的任务切换。
(4)OSCtxSw,OS Context Switch,翻译为:OS上下文切换,或者OS任务切换。任务在切换时必须要保存和回复一些任务的上下文环境,这里的上下文环境主要指R0-R15等寄存器,任务栈(每个任务有一个独立的任务栈,栈内存供这个任务唯一的专用,栈用来维持任务自身的局部变量等)。
2.Ports/os_cpu_c.c
(1)钩子函数(hook)
1.1在很多OS中都有,譬如windows编程中就有这个概念,不止uCOS2有。
1.2钩子函数是这样一种函数,这个函数事先并没有被实现,只有个名字(外壳,空函数名),但是被在该调用的地方调用了。我们可以通过向钩子函数内部填充函数体代码,来让整个体系在运行时执行一些我们自己写的代码。
1.3和钩子函数很像的,原理相同的还有个名字,叫回调函数(recall)。
1.4面向对象的三大特征之一:多态,和钩子函数/回调函数有一定关联。
(2)任务栈
(1)C语言的函数运行是需要栈来支持的,因为局部变量就是栈这种数据结构来实现的。
(2)到底什么是栈?OS通过栈来向C语言提供一种内存管理方式,OS通过栈指针SP来管理栈内存的。
(3)在单片机裸机程序中,整个程序使用一个栈。
(4)OS中不一样,因为OS中有任务的概念,有不同的任务需要切换,所以不同的任务不能共用栈,每个任务都要有自己的私有栈。
(5)操作系统的任务的概念,其实就是一个独立的函数。
(6)OSTaskStkInit的作用就是对任务的栈内存进行初始化,我们每创建一个任务,都应该调用这个函数对任务的私有栈进行初始化,之后再去使用。
TCB: task control block 任务管理块
(3)OS_CPU_SysTickHandler是systick的中断处理程序,systick是OS的时钟节拍。systick每中断一次,OS就运行一个节拍。systcik的中断处理程序中核心是OSTimeTick和OSIntExit这两个函数,在这两个函数中封装了很多节拍处理的工作(主要是任务状态的核实,任务的切换等,譬如之前被挂起的一个更高优先级的任务突然变为就绪态,这时候我们就应该调用任务切换函数进行一个任务切换动作)
(4)OS_CPU_SysTickInit这个是systick的初始化函数,他决定了systick中断被使能从而能够产生中断,还决定了systick隔多久中断一次。通过代码分析,确定systick是1ms。
函数:
OSTimeTick
(1)uC/OS-View是uCOS2的一个可选配件(内核之外的外围功能模块),这东西现在已经废弃了,被uCProbe给替代了,这2个东西都是用来实时监测并调试uCOS内核使用的。
(2)OS_TCB,OS_TaskControlBlock,操作系统的任务管理块,其实就是一个封装好的数据结构,用来管理uCOS2的任务相关的所有数据。
uCOS2中时间单位是tick的个数,也就是说在OS中记录时间的标准是发生了多少次systick。
(3)uCOS2中定义了一个全局变量OSTCBList,这个全局变量作为链表头指针,指向uCOS2维护的TCB双向链表。uCOS2中每一个任务都有一个TCB,这些TCB通过内置的2个指针(OSTCBNext和OSTCBPrev)构建了一个双向链表。这样我们整个uCOS2中所有代码任何位置都可以通过访问全局变量OSTCBList来找到所有的任务的TCB。
(4)uCOS2自己内部定义好了2个任务(及其优先级),这2个任务分别叫:状态任务、空任务。这2个任务的优先级分别是最低优先级和次低优先级。
#define OS_TASK_STAT_PRIO (OS_LOWEST_PRIO - 1)
#define OS_TASK_IDLE_PRIO (OS_LOWEST_PRIO)
这2个任务的作用:状态任务(30)的作用就是来统计OS的各种状态参数(譬如CPU使用率、内存使用率等);空任务(31)的作用就是什么都不干,空。
OSTCBDly元素的作用
(1)TCB的这个元素OSTCBDly涉及到2个功能的实现:一个是任务延时机制,另一个是等待事件超时机制。
(2)当前任务在自己当前不适合运行时(譬如可能要等待一些IO,譬如当前任务要继续执行需要某个条件但是这个条件又不具备无法继续),我们就需要调用delay函数(OSTimeDly或者OSTimeDlyHMSM)来延时相应的时间(譬如10ms,譬如2s),这个delay函数的实现就和OSTCBDly变量有关(delay函数中将要延时的时间换算成tick的数量,然后写入OSTCBDly中,并且将当前任务设置为非就绪态)。具体的实现就是在每一次systick的hanlder中在OSTimeTick函数中去将OSTCBDly减1,然后看是否等于0,如果不等于0说明delay时间还没到,如果等于0说明时间到了。时间到了就要将当前任务恢复为就绪态再调度(如果当前任务是优先级最高的就绪态任务那么就会被调度执行)。
1是就绪态
0是非就绪态
https://www.cnblogs.com/han-bing/p/8944157.html
3Ports/os_cpu_a.asm
在任务切换中
Task Control Block TCB
https://www.cnblogs.com/stupidpeng/p/13650281.html
4.Source/os_time.c
(1)PEND和NOTPEND(PEND_OK/PEND_TO)等对应,PEND关注的是当前任务在等待某个EVENT(sem、mutex等)
(2)SUSPEND和RDY对应,用来描述任务当前的状态的,RDY表示任务处于就绪态,SUSPEND表示任务处于非就绪态(挂起态)