初探UCOSII

来源:互联网 发布:故宫淘宝是故宫开的吗 编辑:程序博客网 时间:2024/05/17 07:50

1、 临界区:有些代码段执行时不允许被中断打断,因此在执行这些代码之前需要关闭系统中断,这些代码执行完成之后则需要重新打开系统中断。(如入栈出栈操作)
2、 如果需要进入临界区,则需要定义内核状态寄存器变量,以保存进入临界区之前的系统状态,退出临界区时恢复CPU之前工作现场。定义如下:

OS_CPU_SR  cpu_sr;   //32位

//进入临界区

#define OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();} 

//退出临界区

#define OS_EXIT_CRITICAL()  {OS_CPU_SR_Restore(cpu_sr);} 

3、 M3的站2生长方向是有高地址向低地址增长,是满栈模式
4、 SVC(系统服务调用)和PendSV(可悬挂系统调用),它们多用在上了操作系统的软件开发中。
5、 SVC用于产生系统函数的调用请求,SVC异常是必须在执行SVC指令后立即得到响应的。PendSV则不同,它可以先付普通的中断一样被悬挂的。OS可以利用它“缓期执行”一个异常——直到其他重要的任务完成后才执行动作。挂起PendSV的方法是:手工往NVIC的PendSV悬挂寄存器中写1.挂起后,如果优先级不高,则将缓期等待执行。
6、 PendSv的典型使用场合是在上下文切换(在不同任务之间切换)。例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是:
1、执行一个系统调用
2、 系统滴答定时器(SysTick)中断。(轮转调度中需要)
3、 轮转调度法中,
7、 钩子函数:指那些插入到某些函数中为扩展这些函数功能的函数。一般地,钩子函数为第三方软件开发人员提供的扩充软件功能的入口点。为了拓展系统功能,UCOSII中提供有大量钩子函数,用户不需要修改UCOSII内核就代码程序,而是只需向钩子函数添加代码就可以扩充UCOSII的功能。
8、 如果需要用到系统的钩子函数,需要在OS_CFG.H中定义

OS_CPU_HOOKS_EN   1

9、 钩子函数的定义如下:
//系统初始化函数OS_Init()开头使用

OSInitHookBegin()    //OSIinit() 

//任务创建函数OSTaskCreate()函数中调用

OSTaskCreateHook()    //OSTaskCreate() 或OSTaskCreateExt() 

我们的任务定义都是这样:

void  MyTask(void *p_arg){        //可选,例如处理p_arg变量        While(1){   //任务主体}}

典型的ARM处理器都会把这个函数的一个参量传递到R0寄存器中
10、 OSTaskStkInit()被任务创建函数调用,所以要在开始时,在栈中作出该任务被中断的假象。
11、 OSTaskStkInit()的工作就是在任务自己的栈中保存CPU的所有寄存器。
12、 一般R0用于传递任务函数的参数。
13、 OS_CPU_SysTickInit()会被第一个任务调用,以便初始化SysTick定时器。OS_CPU_SysTickInit()会调用OS_CPU_SysTickClkFreq()获取系统时钟频率,用户需要为自己的开发板编写此函数获取时钟频率。
14、 我们在移植系统时要把所有与Systick有关的代码全部注释掉,然后编写我们符合自己CPU的的Systick相关的代码。
15、 ALIGN=2表示4字节对齐。ALIGN=n表示2^n字节对齐
16、 Keil编译后烧写到FLASH中占用的大小为Code+RO Data+RW Data
17、 程序运行时,芯片内部RAM使用的空间为:
RW Data+ZIData(没有初始化的可读写变量大小)。
18、 要熟悉NVIC,可参考《Cortex-M3权威指南》
19、 一般将PendSV的可编程优先级设为最低,原因如下:
有中断正在响应时,如果SysTick中断产生系统试图进入线程模式,就会打断中断的响应,从而使中断不能被及时的响应,这对于实时性要求很高的系统时不能容忍的,而PendSV异常能够延时任务切换,完美解决这个窘境,因此只有当所有的ISR响应完成才可以进行任务间的上下文切换,所以需要将PendSV的优先级设为最低。
20、 OSStartHighRdy()启动最高优先级任务,由OSStart()调用,调用前必须先调用OSTaskCreate()创建至少一个用户任务,否则会发生系统崩溃。
21、 当任务放弃CPU使用权时,就会调用OS_TASK_SW()(由OS_Sched()调用),实现任务切换。Cortex-M3中任务切换的工作都放在PendSV中去以加快处理速度,因此OS_TASK_SW()只要挂起(允许)PendSV中断即可。OS_Sched()为任务调度函数。
22、 当中断函数退出时就会调用OSIntExit()来决定是否有优先级最高的任务需要执行,若有,则OSIntExit()调用OSIntCtxSw()进行任务切换。
23、 当任务做延时或者因为等待某个资源是就会调用OSCtxSw()进行任务调度,由任务调度进行任务切换。
24、 当调用OS_CPU_PendSVHandler()时,CPU就会自动保存XPSR、PC、LR、R12、R0—R3寄存器值到堆栈中,保存之后,CPU的栈指针SP就会切换到使用主栈指针MSP上,我们只要检测入栈指针PSP是否为NULL就可以知道是否需要进行任务切换,因此当我们第一次启动系统任务时,OSStartHighRdy()就会把PSP设为NULL,避免系统误判为已经进行任务切换。
25、 在函数中预先插入钩子函数,以便后续拓展此函数的功能,如果无需拓展可以将钩子函数的函数体置空。
26、 STM指令用于批量存储,LDM用于批量加载,主要用于现场保护、数据复制、参数传递。语法格式如下:

STM{cond}  mond  Rn{!}, reglist{^}LDM{cond}  mond  Rn{!},reglist{^}

其中mond共有八种,分别为:
IA 数据传递后地址加4
IB 数据传递前地址加4
DA 数据传递后地址减4
DB 数据传递前地址减4
用于数据传递;
I–Increase ;D—Decrease ;A—After ; B—Before
FD 满递减堆栈
ED 空递减堆栈
FA 满递增堆栈
EA 空递增堆栈
用于保护现场;
F—Full ; E—Empty ; D—Decrease; A—Add
例如DB表示的内存地址变化如下:
Start_address = Rn – (Number_Of_Set_Bits(reglist)*4);
End_address = Rn-4;
Number_Of_Set_Bits(reglist)求出寄存器的个数。
以下是任务切换时的寄存器情况:

任务切换时的寄存器情况

0 0
原创粉丝点击