此文共连载分析三个uCOS-Ⅱ的三个源码文件夹:uC-CPU 、uC-LIB 、uCOS-Ⅱ
uC-LIB文件夹目录:
ARM-Cortex-M3 / cpu_a.asm、cpu_c.c、cpu.h
cpu_def.h
cpu_def.h
- 这个文件中定义了一些 CPU 有关的宏定义,分为三类:
1、CPU 字节长度的定义,理想情况下 CPU 的字长应该是由 sizeof() 函数计算出来的,但是 sizeof() 函数必须在 CPU 运行中才能进行计算,所以在 uCOS 中直接用宏定义定义了出来
#define CPU_WORD_SIZE_32 4 // 定义 CPU 字节长度为 4 字节
2、CPU 字节顺序的定义,也就是 CPU 的大/小端模式的定义。
#define CPU_ENDIAN_TYPE_NONE 0 // 不知道是大端模式还是小端模式
#define CPU_ENDIAN_TYPE_BIG 1 // 大端模式
#define CPU_ENDIAN_TYPE_LITTLE 2 // 小端模式
3、临界区的定义和配置,临界区是指一个共用资源的程序片段,但共用资源程序片段一次只能被一个线程占用,当有一个线程正在访问临界区时,其他线程或进程就必须等待,以临界区共用资源的互斥使用(举例:打印机的使用,一个用户正在使用打印机,在未使用完成时,其他用户只能等待前一用户使用完成后才能使用)。
#define CPU_CRITICAL_METHOD_NONE 0 // 发生临界区问题是不解决
// 在有线程进入临界区前,暂时禁止中断响应,防止高优先级中断打断正在临界区的线程,在退出临界区时再使能中断
#define CPU_CRITICAL_METHOD_INT_DIS_EN 1 // 用禁止/使能中断的方法解决临界区问题
#define CPU_CRITICAL_METHOD_STATUS_STK 2 // 将临界区状态保存在栈中
#define CPU_CRITICAL_METHOD_STATUS_LOCAL 3 // 将临界区状态保存在局部变量中
cpu.h
-
核心的就是进入临界区和退出临界区的两个宏
- 其他的都是一些数据类型重定义和 cpu_c.c 文件中函数的声明
//设置了临界区解决办法,将临界区状态保存在局部变量中
# define CPU_CFG_CRITICAL_METHOD CPU_CRITICAL_METHOD_STATUS_LOCAL
//进入临界区前调用这个宏,实现将 CPSR 寄存器备份,然后关闭中断响应
# define CPU_CRITICAL_ENTER() { cpu_sr = CPU_SR_Save(); }
//退出临界区后调用这个宏,实现将 CPSR 寄存器还原,中断响应开启
# define CPU_CRITICAL_EXIT() { CPU_SR_Restore(cpu_sr); }
cpu_c.c
- 首先是关于对位带操作的宏定义,定义了 SRAM 内存的位带访问地址范围和外设寄存器的位带访问地址范围。
- 然后是函数的定义,包括位带清零和置位、使能和禁止 CPU 内部中断源、设置和读取中断源的优先级的函数,这些函数的实现都用到了 NVIC 模块的设置寄存器的位定义和进入/退出临界区时的两个设置宏。
- uCOS-Ⅱ 中的临界区解决办法用的全部都是 #define CPU_CRITICAL_METHOD_STATUS_LOCAL 这一种办法,其他两个办法没有使用。
- 其中存储 CPSR 寄存器的局部变量是 CPU_SR 类型的 cpu_sr,这个局部变量是配合进入/退出临界区的两个配置宏进行使用的,看到这个变量定义,后面一定就用到了临界区的操作。
cpu_a.asm
文件中用 EXPORT 导出了多个函数,定义了一些汇编语言书写的函数:
EXPORT CPU_IntDis // 全局中断的禁止
EXPORT CPU_IntEn // 全局中断的使能
EXPORT CPU_SR_Save // 将 CPSR 寄存器内容保存到 R0 寄存器中,然后禁止全局中断
EXPORT CPU_SR_Restore // 将 R0 寄存器内容恢复到 CPSR 寄存器中
EXPORT CPU_CntLeadZeros // 前导零计数
EXPORT CPU_RevBits // 二进制层面取反, 1010 ---> 0101
EXPORT CPU_WaitForInt // CPU 立即进入睡眠模式,等待中断唤醒
EXPORT CPU_WaitForExcept // CPU 进入睡眠模式,等待异常唤醒
来源:51CTO
作者:YPB39155
链接:https://blog.51cto.com/ypb39155/2097523