uC/OS--II在STM32F103ZET6上的移植

      本文是在参考野火移植uC/OS教程的基础上写的一点心得,如有误请指正。

      第一件事就是去下载uC/OS的源码啦,要用什么版本的你自己定,我用的是v2.86,v2.90也可以。http://micrium.com/,要自己注册账户哦,免费下载。

      解压后有几个重要的文件,AppNotes/ANxx_ST_XX,这个是uC/OS作者在stm32上移植时的写的移植笔记,很有借鉴价值。接下来直奔主题,要移植的几个文件是os_cpu.h(定义数据类型、处理器相关代码、声明函数原型);os_cpu.asm(关于任务切换的汇编代码编写,要写的代码很少,稍微理解下就懂了);os_cpu.c(用户自己定的功能函数,和一个堆栈初始化函数);os_dbg.c(内核调试数据和函数,我们用不到);

     os_cpu.h的移植内容用一句话概括:数据类型、栈增长方向(从高向低)、进入临界段(方法3)、函数声明

     os_cpu.c要移植10 个相当简单的 C 函数:9 个钩子函数和 1个任务堆栈结构初始化函数。所谓钩子函数,指那些插入到某些函数中为扩展这些函数功能的函数。一般地,钩子函数为第三方软件开发人员提供扩充软件功能的入口点。为了拓展系统功能,uC/OS-II 中提供有大量的钩子函数,用户不需要修改 uC/OS-II 内核代码程序,而只需要向钩子函数添加代码就可以扩充 uC/OS-II 的功能。要用到这些钩子函数,需要在 OS_CFG.H 中定义 OS_CPU_HOOKS_EN 为 1。这些钩子函数是必须声明的,但不是必须定义的,只是为了拓展你的系统功能而已。 

        堆栈初始化函数需要提出来说下:

       OSTaskStkInit()被任务创建函数调用,所以要在开始时,在栈中作出该任务好像刚被中断一样的假象。 在 ARM 内核中,函数中断后,xPSR,PC,LR,R12,R3-R0 被自动保存到栈中的,R11-R4 如果需要保存,只能手工保存。为了模拟被中断后的假象,OSTaskStkInit()的工作就是在任务自己的栈中保存 cpu 的所有寄存器。R1~R12寄存中存的值没啥意义,只是为了方便调试,因为实际的任务还没运行,运行时就会把一些必要的寄存器保存到堆栈中。解释下xPSR、PC、LR、R0为啥这样赋值。xPSR = 0x01000000L,xPSR T 位(第 24 位)置 1,否则第一次执行任务时 Fault, PC 必须指向任务入口, R14 = 0xFFFFFFFEL,最低 4 位为 E,
是一个非法值,主要目的是不让使用 R14,即任务是不能返回的。 R0 用于传递任务函数的参数,因此等于 p_arg。

       os_cpu.asm:概括起来包括全局变量的声明,代码段汇编程序格式,PendSV的作用,开关中断的汇编代码、任务切换相关的几个函数。直接说重点PendSV,SVC是系统服务调用引发的异常,他俩都属于NMI不可屏蔽中断,SVC必须立即得到响应。PendSV跟他不一样,他可以缓期执行终端服务,顾名思义就是可以先悬起它,等更重要的事做完了再来完成它里面要做的事。悬起PendSV中断的方法是往NVIC控制/状态寄存器(地址0XE000ED04)的PENDSVSET位写1,同时要将PendSV的中断优先级定成最低255才行哦,不是说了吗要等其他更重要的事做完才来做PendSV中的事,就是往系统异常优先级寄存器PRI_14(地址0XE000ED22)中写入255.

      由于移植uC/OS中用得是方法3进入临界段,所以开关中断的代码如下

      

      PRIMASK :这是个只有1个位的寄存器。当它置1时,就关掉所有可屏蔽的异常,只剩下NMI和硬fault可以响应。它的缺省值是0,表示没有关中断。 

      Cortex-M3为了快速地开关中断,专门设置了一条 CPS 指令:
                                                                CPSID I  ;PRIMASK=1,;关中断
                                                                CPSIE I ;PRIMASK=0,;开中断

      好了,下面注重讲下任务切换的几个相关函数。

     首先要简单的写下OSStartHighRdy()--启动最高优先级任务,由 OSStart()里调用,调用前必须先调用OSTaskCreate 创建至少一个用户任务,否则系统会发生崩毁。OSStartHighRdy()就把OSRunning标志置位,设置PendSV优先级、悬起PendSV。

     任务切换函数OSCtxSW()、OSIntCtxSW()内容一样,都是将PendSV悬起,真正的任务切换工作过是放到PendSV中断服务函数中做的,这样系统的任务运行的效率会很高,不会出现因为一个NMI出现,而且NMI要切到普通任务而出现的将ISR执行周期延长的现象。

     PendSV中断服务程序如下:

                        

    由于M3在进中断时已经把xPSR、PC、LR、R12和R0\R1\R2\R3保存进栈。所以我只用自己手动保存R4~R11进栈。

    总的理解PendSV中断服务函数如下:

                    1、如果不是第一次运行任务,则保存R1~R11,保存当前栈指针到当前TCB。若是第一次运行任务,则省略这两个工作,因为第一次运行任务时已经将R4~R11入栈

                    2、使用用户自己的钩子函数

                    3、获取最高优先级的TCB,从而得到它的堆栈指针

                    4、进入最高优先级任务的堆栈,POP出R4~R11;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值