μ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做四旋翼的主控, ...
随机推荐
- 微信小程序--相关资料
微信小程序Demo https://github.com/zce/weapp-demojustjavac/awesomewechatweapp: 微信小程序开发资源汇总 https://gith ...
- BizTalk RosettaNet 配置导入与导出
更多内容请查看:BizTalk动手实验系列目录 BizTalk 开发系列 BizTalk 培训/项目开发/技术支持请联系:Email:cbcye ...
- Linux将yum源设置为阿里云的镜像源
第一步:备份原有镜像源 mv /etc/yum.repo.d/Centos-Base.repo /etc/yum.repo.d/Centos-Base.repo.bak 第二步:下载阿里云的镜像源 w ...
- 解决ubuntu下IntelliJ IDEA无法锁定到启动器的问题
参考:https://www.zhihu.com/question/31626161 在目录~/.local/share/applications 中找到以前的IDEA的.desktop文件,删掉即可
- 火车头采集器如何采集QQ群成员中的QQ号
如何采集QQ群群员QQ号,采集QQ号,批量采集QQ号 众所周知,QQ群群员QQ号无法导出,即使会员也不可以,那我们只能通过三方工具来实现我们的要求,那今天我们讲讲如何通过火车采集器来采集QQ群群员QQ ...
- css如何实现一个元素高度固定宽度按比例显示?
用padding-top百分比可以实现宽度固定高度按比例展示,现在的需求是对一个video视频的盒子div高度是固定的,宽度如何按比例展示? 解决后效果如图: 红框标注的即是我在上面高度比例固定的范围 ...
- SQL查询无限层级结构的所有下级,所有上级
无限层级结构的table1表,Id(主键),ParentId(父级id)查询某个Id的所有下级或所有上级,使用WITH AS,UNION ALL 查询 1.查询Id为1所有的下级 WITH T AS( ...
- javascript:变量的作用域
window.onload = function (){ // 1) 在if或else代码块中声明的变量,在代码块的外面也可以取到 if(1==1){ var b = 12; }else{ var b ...
- Redis密码设置与访问限制
https://www.cnblogs.com/ghjbk/p/7682041.html https://ruby-china.org/topics/28094
- go关键字之struct定义声明方式
type Student struct{ name string age int } var stu Student stu.name,stu.age = "张三”,10 stu2 := S ...