[toc]
1. 关于ucosii的移植
1. 总体步骤
- 前期了解
- 目标芯片(内核)
- ucosii内核原理
2. ucosii内核原理
ucosii内核可分为: 任务调度,任务同步,内存管理,三部分
任务调度
- 为每个任务分配一个不同的优先级
以下情况会发生任务切换
- 任务等待资源或者自我延时
- 退出中断
SysTick中断是os的”心跳”,会发生周期性任务切换,所以必须调用OSTimeTick();
os_core.c是核心,包含内核初始化,任务切换,时间块管理等。其中时间块是各个同步量的基础
os_sem.c 各个同步量管理代码
os_mem.c内存管理代码
os_time.c 时间管理,主要做各种延时
os_task.c 任务管理代码一个定时器大体由,定时时间,回调函数,属性。
当定时器时间到了就做一次回调函数的处理,定时器属性说明定时器是周期性的定时,还是一次定时
如果用户使能了OS_TMR_EN, ucosii会在内部创建一个定时器任务,负责各个定时器。这个任务有硬件定时器的中断函数中调用OSTmrSignal()去激活。本质上说os_tmr.c中的定时器室友一个硬件定时器分化出来的
- 默认情况下由SysTick中断莉通过OSTimeTickHook() 去激活定时器任务
3. 移植相关文件
- os_cpu.h 进行数据类型定义,处理器相关代码和几个函数原型
os_cpu_c.c 定义一些用户hook函数
os_cpu_a.asm 移植需要用汇编代码完成的函数,主要是任务切换函数
os_dbg.c 内核调试相关数据核函数,可以不改
2. 关于ucosii在STM32上的移植
1. 前期了解Cortex-M3
寄存器组
- R0-R12: 通用寄存器
R13: 堆栈寄存器(MSP和PSP, 但只能看见一个<目前正在使用的>)
- MSP:异常服务和应用程序
- PSP: 应用程序
- 复位后使用的是MSP
R14: 连接寄存器,存储返回地址,又名LR
- R15: 程序计数寄存器,PC
程序状态字寄存器组,PSRs
- 中断屏蔽寄存器组, PRIMASK, FAULTMASK, BASEPRI(控制异常的使用和除能)
- 控制寄存器, CONTROL(1. 定义特权级别, 2. 选择当前使用的堆栈指针)
PSRs分为:
- 应用程序 PSR(SPSR)
- 中断号 PSR(IPSR)
- 执行 PSR (EPSR)
每个都是32位
操作模式和特权级别
- 操作模式: 处理者模式和线程模式
- 异常处理: 处理者模式
- 主程序: 线程模式
ucossii不区分特权模式和用户级,一直处于特权级
异常: 系统异常(1-15), 外部中断(大于15)
- 优先级: 3个固定的高优先级,和256个可编程优先级
- NVIC中每个中断都有一个优先级配置寄存器(1byte),并不是所有都在用
- 寄存器是以MSB对齐的,
- 每个中断优先级配置寄存器7:4位有效,7:5位确定抢占优先级,位4确定亚优先级
- 分为抢占优先级和亚优先级
- NVIC中应用程序中断及复位控制寄存器AIRCR的优先级分组(10:8)描述了如何划分抢占式优先级和亚优先级
相同抢占优先级的中断不能嵌套
中断优先级寄存器阵列 0XE000_E400 - 0xE000_E4EF共240个
- 系统异常优先级寄存器 0xE000_ED18 - 0xE000_ED23共12个
优先级相同看中断号,小的优先
向量表 初始0x00000000 可通过向量表偏移量寄存器(VTOR:0xE000_ED08)更改
uclinux是针对没有MMU的嵌入式系统而设计的
PendSV中断主要用于上下文切换,也就是任务切换,是最重要的中断
- 该中断是手工往NVIC的PendSV悬起寄存器中写1产生的
- 该中断优先级最低
NVIC负责芯片的中断管理
中断的行为
- xPSR, PC, LR, R12以及R3-R0入栈
- 取向量
- 选择堆栈指针MSP/PSP,更新SP,更新LR, 更新PC
异常返回
- 进入中断时LR寄存器的值会被自动更新,通过把更新后的值EXC_RETURN往PC里写来识别返回动作
中断服务程序如果是C代码编写,汇编后的代码函数结尾一般是reti
汇编和C的接口
- 当主调函数需要传递参数时,它们使用R0-R3,其中R0传递第一个,R2传递第二个…在返回时,把返回值写到R0中
- 在函数中,用汇编写代码时,R0-R3, R12可以随便使用,R4-R11必须先push后pop
2. 移植过程
- *