μCOS-II移植 - 基于CortexM3
μCOS-II是一个经典的RTOS。
任务切换对于RTOS来说是最基本也是最核心的部分,除此之外还有任务调度算法。
先来看看基于stm32f107的任务切换代码:
;********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
; the first task to start.
;
; 2) OSStartHighRdy() MUST:
; a) Setup PendSV exception priority to lowest;
; b) Set initial PSP to 0, to tell context switcher this is first run;
; c) Set the main stack to OS_CPU_ExceptStkBase;
; d) Set OSRunning to TRUE;
; e) Trigger PendSV exception;
; f) Enable interrupts (tasks will run with interrupts enabled).
;******************************************************************************************************** OSStartHighRdy
LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0] MOVS R0, # ; Set the PSP to 0 for initial context switch call
MSR PSP, R0 LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase
LDR R1, [R0]
MSR MSP, R1 LDR R0, =OSRunning ; OSRunning = TRUE
MOVS R1, #
STRB R1, [R0] LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0] CPSIE I ; Enable interrupts at processor level OSStartHang
B OSStartHang ; Should never get here ;********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
; void OSCtxSw(void)
;
; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function
; triggers the PendSV exception which is where the real work is done.
;******************************************************************************************************** OSCtxSw
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR ;********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From interrupt level)
; void OSIntCtxSw(void)
;
; Notes: 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
; the result of an interrupt. This function simply triggers a PendSV exception which will
; be handled when there are no more interrupts active and interrupts are enabled.
;******************************************************************************************************** OSIntCtxSw
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR ;********************************************************************************************************
; HANDLE PendSV EXCEPTION
; void OS_CPU_PendSVHandler(void)
;
; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
; context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the
; processor context on any exception, and restores same on return from exception. So only
; saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception
; this way means that context saving and restoring is identical whether it is initiated from
; a thread or occurs due to an interrupt or exception.
;
; 2) Pseudo-code is:
; a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
; b) Save remaining regs r4-r11 on process stack;
; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
; d) Call OSTaskSwHook();
; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
; h) Restore R4-R11 from new process stack;
; i) Perform exception return which will restore remaining context.
;
; 3) On entry into PendSV handler:
; a) The following have been saved on the process stack (by processor):
; xPSR, PC, LR, R12, R0-R3
; b) Processor mode is switched to Handler mode (from Thread mode)
; c) Stack is Main stack (switched from Process stack)
; d) OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
; know that it will only be run when no other exception or interrupt is active, and
; therefore safe to assume that context being switched out was using the process stack (PSP).
;******************************************************************************************************** OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11} LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out ; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14} LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0] LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0] LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore remaining context
OSPendSV()是 PendSV Handler 的中断处理函数(的名称),它实现了上下文切换。这种实现
方式对于 ARM Cortex-M3 来说是强烈推荐的。这是因为对于任何异常,ARM Cortex-M3 可以
自动的保存(进入异常)和恢复上下文(退出异常)的 一部分内容。因此 PendSV handler 只
需要保存和恢复 R4-R11 和堆栈指针这些剩余的上下文。使用了 PendSV 的异常机制,意味
着,无论是由任务触发还是由中断或异常触发的上下文切换都可以用同一种方法实现。
置 注意你必须在异常向量表的位置 14 处设置一个指针指向 OSPendSV()。
PendSV handler 的伪代码如下:
OSPendSV:
if (PSP != NULL) { ()
Save R4-R11 onto task stack; ()
OSTCBCur->OSTCBStkPtr = SP; ()
}
OSTaskSwHook(); ()
OSPrioCur = OSPrioHighRdy; ()
OSTCBCur = OSTCBHighRdy; ()
PSP = OSTCBHighRdy->OSTCBStkPtr; ()
Restore R4-R11 from new task stack; ()
Return from exception; ()
(0) 注意当 OSPendSV 被 CPU 运行,CPU 会自动地保存 xPSR、PC、LR、R12 和 R0-R13 到
任务的堆栈。当将部分上下文保存到相应的任务的堆栈后,CPU 要切换堆栈指针了,
转而使用 SP_main 来运行剩下的中断程序。
(1) 这里我们检查 SP_process 堆栈指针是否为 NULL。重申:OSStartHighRdy()函数将
SP_process 置 NULL 来达到避免当运行第一个任务时保存任务的上下文的目的。
(2) 如果 PendSV()确实被触发来实现一个完整的任务切换,则我们简单的保存上下的寄
存器的值(R4-R11)
(3) 一旦正在被切换的任务的上下文被保存,我们简单的保存任务的堆栈指针
(SP_process)到正在被切换的任务的 OS_TCB。
(4) 接下来我们调用 UCOS 上下文切换的钩子函数(参见 OS_CPU_C.C)。
(5) 像其他硬件平台上移植 UCOS 的做法一样,我们需要赋值新的高优先级的任务的指
针到当前的任务的指针。
(6) 同上,我们需要复制 OSTCBHighRdy 进 OSTCBCur。
(7) 接下来,我们恢复我们希望切换的那个任务的当前栈顶指针。重申,栈顶指针保存
在变量 OSTCBHighRdy->OSTCBStkPtr 中。方便起见,UCOS 总是将.OSTCBStkPtr 放在结
构体 OS_TCB 的开头,这样避免了去查找 SP 的 offset,offset 总是 0。
(8) 我们从任务的堆栈结构中恢复任务的上下文,为任务的执行做准备。
(9) 实现一个异常的返回,这将促使 ARM Cortex-M3 自动从相应的任务堆栈结构中恢复
R3-R12、LR、PC 和 xPSR 寄存器的值。至此便正在运行新任务了。
注意:PendSV Handler 是不可抢占的是不可被中断的,以此保证上下文自动切换。如果上下
文切换时发生中断,则新任务恢复后(上下文切换完毕后)立即执行相应的中断服务程序。
OSStartHighRdy将PSP置零,设置并触发了PendSV,在OS_CPU_PendSVHandler中,会跳过PSP和r4-r11的压栈,这是因为是第一次执行任务切换,之前没有有意义的任务需要保存。
同时可以发现任务级别的切换和中断级别的切换是一样的。
对于移植μCOS-II,基本需要专为操作系统而生的SYSTICK提供的OS心跳、任务切换和禁止使能中断就可以了。
μCOS-II移植 - 基于CortexM3的更多相关文章
- emWin 移植 - 基于红牛开发板
一直想利用所学的东西自己设计一个精致一些的作品,手头正好有一块红牛开发板,就先用它来写一些软件,熟悉一下过程和一些想法的可行性.首先当然是选择一个操作系统了,对比了几种之后选择了emWin.那就移植一 ...
- NIOS II下基于中断的UART接收和发送设计示例代码
#include "sys/alt_stdio.h" #include "altera_avalon_uart_regs.h" #include "s ...
- STM32固件库3.5+uCOS2.86移植(转自暴走的工程师)
考了很多移植的资料和代码,终于移植好了...应该是完美移植吧~~哈哈哈~~ 编译环境是IAR 工程适用于STM32F10X大容量产品,如果不是,请自行修改启动文件和工程配置 编译器优化等级最高...这 ...
- ARM Cortex-M3内核的巨大优势
ARM Cortex-M3相比于ARM其他系列微控制器,具有以下优势或特点: 1. 三级流水线+分支预测 ARM Cortex-M3与ARM7内核一样,采用适合于微控制器应用的三级流水线,但增加了分支 ...
- Hello China操作系统STM32移植指南(一)
Hello China操作系统移植指南 首先说明一下,为了适应更多的文化背景,对Hello China操作系统的名字做了修改,修改为"Hello X",或者连接在一起,写为&quo ...
- Cortex-M3
大家听说过Cortex-M3吗?在嵌入式处理器的世界,cortex-M3是一位人见人爱的后生.它的成本和功耗低,可配置性很高.如今,很多ARM的工程师加入了cortex-M3的学习与开发中,WIZne ...
- ucos ii 百度官方介绍
μC/OS II(Micro-Controller Operating System Two)是一个可以基于ROM运行的.可裁剪的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处 ...
- 【LiteOS】Liteos移植篇
目录 前言 链接 参考 笔录草稿 移植(2018) 移植获取 (Cortex-M 内核) 主要文件夹分析 移植过程 1. 拷贝文件 2. 创建工程分组 3. 添加头文件路径 4. 兼容 C99 模式 ...
- 六轴加速度传感器MPU6050官方DMP库到瑞萨RL78/G13的移植
2015年的电赛已经结束了.赛前接到器件清单的时候,看到带防护圈的多旋翼飞行器赫然在列,又给了一个瑞萨RL78/G13的MCU,于是自然联想到13年的电赛,觉得多半是拿RL78/G13做四旋翼的主控, ...
随机推荐
- puppeteer:官方出品的chrome浏览器自动化测试工具
puppeteer发布应该有一段时间了,这两天正好基于该工具写了一些自动化解决方案,在这里抛砖引给大家介绍一下. 官方描述: Puppeteer is a Node library which pro ...
- 使用git和github进行协同开发流程
(本文假设各位已经对基本git的基本概念.操作有一定的理解,如无相关git知识,可以参考Pro Git这本书进行相关的学习和练习) 很多项目开发都会采用git这一优秀的分布式版本管理工具进行项目版本管 ...
- js命名空间的函数namespace
这是一个扩展函数,需要初期加载的时候加载到适当的位置. 具体函数体如下: $.namespace = function() { var a=arguments, o=null, i, j, d; fo ...
- java通过jdbc访问mysql,update数据返回值的思考
java通过jdbc访问mysql,update数据返回值的思考 先不说那么多,把Java代码贴出来吧. public static void main(String[] args) throws I ...
- 【NLP】MT中BLEU评分机制
参考博客:https://blog.csdn.net/guolindonggld/article/details/56966200 原著论文:http://www.aclweb.org/antholo ...
- Django 跨域问题
当使用Django 做接口时,被html5 或者app访问时 存在跨域问题 导致无法请求到数据,具体解决办法如下: 跨域问题解决 安装pip install django-cors-headers修改 ...
- 从unity丢图标到unity进不去桌面
现象1: 用了一年多的unity的右上角的网络图标和网易云音乐的图标消失不见了,我也不记得最近有update或upgrade过,然而这两个功能还是可以正常用 解决1: 安装Gnome,果然相应的图标就 ...
- 【Zookeeper系列】ZooKeeper安装配置(转)
原文链接:https://www.cnblogs.com/sunddenly/p/4018459.html 一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪 ...
- JS中实现种子随机数
参数: 详谈JS中实现种子随机数及作用 我在Egret里这么写... class NumberTool{ /**种子(任意默认值5)*/ public static seed:number = 5; ...
- 宣布推出针对 Microsoft OneDrive 和 SharePoint 的 Autodesk AutoCAD 新集成
在 OneDrive 和 SharePoint,我们的愿景是随时随地为你的团队提供简单而安全的文件访问.无论你的职位.专业或行业是什么,我们将始终致力于扩展和连接你最重视的内容.今天,我们发布了与 A ...