您现在的位置是:首页 >技术教程 >ARM-M架构移植UCOS操作系统网站首页技术教程
ARM-M架构移植UCOS操作系统
最近准备面试,把本科到现在的一些比赛相关的东西整理一下。那些年在飞思卡尔在K60单片机上的UCOSII移植(哎,心酸...)
一、首先看下UCOSII的文件结构:
一些核心的文件解释:
【1、头文件】:
includes.h:每个.c文件需要包含的头文件,注释掉不需要的头文件,可以配合裁剪
os_cfg.h:对系统的配置和裁剪;(选择宏定义关闭某些功能(设置时间频率1000hz,配合滴答定时器的load值可以确定ucos的时基,用来确定调度的频率),如下图比如说关闭hooks和debug);
os_cpu.h:为了适应数据类型进行重定义,重点关注OS_STK这个数据类型,我们在定义任务堆栈的时候就是该类型数据;
【2、C文件】:
os_cpu_c.c
【3、汇编文件】:
os_cpu_a.asm:
IMPORT表示这是一个外部变量,不是在本程序内定义的,EXPORT则表示该文件内这些函数,供其他文件调用;
圈1:OSStart()调用,开启多任务
圈2:触发PendSV中断,调用圈4,任务切换
圈3:开关中断
圈4:上下文切换(任务切换的最后调用)
二、系统移植要解决的问题
对比学习是效率最好的,当初移植也是参照stm32f1去移植的!
在移植时ARM-M3/M4系统有两个比较重要的文件:系统启动文件和中断服务函数文件:
K60(M4内核)/STM32F1(M3内核):startup_MK60D10.s/startup_stm32f10x_md.s
system_MK60D10.c/stm32f10x_it.c
1、解决上下文切换函数的冲突:PendSV_Handler
一般,在ARM-M3/M4系统的板载支持包会有一个叫 statup_xxx.s 的启动文件(K60和stm32f1分别是[startup_MK60D10.s/startup_stm32f10x_md.s]),文件中会定义CPU相关的中断向量表:
其中重要的,如
SVC_Handler[产生系统调用就会产生svc异常,需要立即执行]、
PendSV_Handler[可悬起的系统调用,可以缓期执行动作,用于上下文切换]、
SysTick_Handler等[这几个中断接口只在启动文件中使用EXPORT导出符号,具体实现会在CPU的板载支持包中的中断服务函数的文件里实现([system_MK60D10.c/stm32f10x_it.c])、
Reset_Handler[这个就在启动文件中实现的,完成系统工作频率的初始化,并跳转到__main函数,进入c环境开始运行应用层代码]),如下所示:
问题:同样在UCOSII的源码文件os_cpu_a.asm中定义了PendSV_Handler函数,由于上下文切换需要极快的执行效率,因此保留ucosii中的汇编实现,注释掉M3/M4系统的板载支持的C语言实现;
2、M3/M4系统的会提供滴答定时器,将它作为UC系统的任务调度时钟:SysTick_Handler
在M3/M4系统的启动文件【startup_MK60D10.s/startup_stm32f10x_md.s】,找到滴答定时器对应的中断函数表(函数名称),并在相应文件中实现该函数:(stm32是在中断服务文件stm32f10x_it.c中实现的,我在移植K60直接将它添加到os_cpu_c.c中去实现的也没问题):
这个函数主要是通过定时器装载值,出发定时器中断,然后去执行任务调度(ucos调度策略是任务优先级);中断频率在os_cfg.h文件的[OS_TICKS_PER_SEC]参数设置;
3、修改任务堆栈函数:OSTaskStkInit
添加需要手动入栈的寄存器,实际上,任务堆栈函数是在任务创建函数中调用OSTaskCreate,Stack frame一开始的地址是一个空区域。所以在修改UCOSII的堆栈初始化函数OSTaskStkInit()的时侯堆栈的向第一个位置写0就是这么来的,【也就是OSTaskCreate函数传入第二个参数为0,向R0写0】。xPSP寄存器的bit9被用来指示SP(堆栈指针)是否需要对齐,该函数将xPSR、PC、LR(R14)、R12、R0-R3这8个寄存器自动入栈,其余的8个寄存器R4-R11就需要我们自己手动入栈了,入栈顺序不能乱了。如果使用M4的FPU(浮点单元),则还需要入栈额外的寄存器,就需要去查阅对应手册。
4、系统裁剪:
os_cfg.h(节拍设置、功能选配等)、头文件:includes.h
5、应用程序main函数:在启动OS之前,一定要先完成 【系统时基的配置】以及【滴答定时器装载值的配置】,以保证UCOS按照固定频率触发中断,进行SysTick_Handler的调用,判断任务时候切换,进而触发PendSV进行任务切换:
--------------------------------------------------可以去写两个任务测试一下了... ...