您现在的位置是:首页 >技术教程 >ARM-M架构移植UCOS操作系统网站首页技术教程

ARM-M架构移植UCOS操作系统

bug大湿 2024-10-06 00:01:05
简介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进行任务切换:

 --------------------------------------------------可以去写两个任务测试一下了... ...

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。