os_cpu_c.c
定位到源码的uCOS-II/Ports/ARM-Cortex-M3/Generic/IAR/os_cpu_c.c:
os_cpu_c.c定义了9个钩子(Hook)函数和一个堆栈初始化函数。
所谓钩子函数,是那些插入到某些函数中以扩展这些功能的函数,一般钩子函数是为第三方软件开发人员提供的扩充软件功能的入口。为了系统使用者扩展系统功能,uCOS-II中提供很多的钩子函数,使用者可以不修改uCOS-II的源码,只是往对应的钩子函数添加代码即可扩充uCOS-II的功能。
虽说uCOS-II提供了许多钩子函数,但在实际移植我们可以实现的也就9个,这9个就位于当前文件os_cpu_c.c。钩子函数的声明是必须的,但不是必须定义。
1. 系统定时器SysTick寄存器定义
/*
*********************************************************************************************************
* SYS TICK DEFINES
*********************************************************************************************************
*/#define OS_CPU_CM3_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */
#define OS_CPU_CM3_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload Value Reg. */
#define OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */
#define OS_CPU_CM3_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal Value Reg. */
#define OS_CPU_CM3_NVIC_PRIO_ST (*((volatile INT8U *)0xE000ED23uL)) /* SysTick Handler Prio Reg. */#define OS_CPU_CM3_NVIC_ST_CTRL_COUNT 0x00010000uL /* Count flag. */
#define OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC 0x00000004uL /* Clock Source. */
#define OS_CPU_CM3_NVIC_ST_CTRL_INTEN 0x00000002uL /* Interrupt enable. */
#define OS_CPU_CM3_NVIC_ST_CTRL_ENABLE 0x00000001uL /* Counter mode. */
#define OS_CPU_CM3_NVIC_PRIO_MIN 0xFFu /* Min handler prio. */
2. 系统初始化函数开头时会调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u //OS_CPU_HOOKS_EN宏在os_cfg.h中
//系统初始化函数OSInit()开头调用
void OSInitHookBegin (void) //系统初始化函数开头的钩子函数
{INT32U size;OS_STK *pstk;/* Clear exception stack for stack checking.*/pstk = &OS_CPU_ExceptStk[0];size = OS_CPU_EXCEPT_STK_SIZE;while (size > 0u) {size--;*pstk++ = (OS_STK)0;}OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u];#if OS_TMR_EN > 0uOSTmrCtr = 0u; //当使用os_tmr.c定时器管理模块,初始化系统节拍计数数量OSTmrCtr为0,每个节拍会使得OSTmrCtr加1
#endif
}
#endif
OS_CPU_HOOKS_EN是以操作系统配置宏。在uCOS-II中,类似于xxxx_EN这样的宏都是操作系统配置宏,它们一般被宏定义在os_cpu_cfg.h文件中。用于裁剪系统功能。这个文件理论是需要系统使用者编写的,但是我们一般采用移植的方法,使用现有的文件加以修改即可。
OS_CPU_HOOKS_EN大于0表示当前系统使用了钩子函数这个功能。下来的8个钩子函数也都有OS_CPU_HOOKS_EN的判断操作。
3. 系统初始化函数结束时会调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSInitHookEnd (void) //系统初始化函数结束的钩子函数
{
}
#endif
4. 创建任务时会调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTaskCreateHook (OS_TCB *ptcb) //创建任务的钩子函数
{
#if OS_APP_HOOKS_EN > 0u //若有定义应用任务App_TaskCreateHook(ptcb); //调用应用任务创建的钩子函数
#else //否则(void)ptcb; //告诉编译器ptcb没有用到。
#endif
}
#endif
这个函数是在OSTaskCreate()或OSTaskCreateExt()中调用的。
5. 删除任务时会调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTaskDelHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0uApp_TaskDelHook(ptcb);
#else(void)ptcb;
#endif
}
#endif
6. 空闲任务调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTaskIdleHook (void) //空闲任务钩子函数
{
#if OS_APP_HOOKS_EN > 0uApp_TaskIdleHook();
#endif
}
#endif
7. 任务返回时调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTaskReturnHook (OS_TCB *ptcb) //任务返回的钩子函数
{
#if OS_APP_HOOKS_EN > 0uApp_TaskReturnHook(ptcb);
#else(void)ptcb;
#endif
}
#endif
8. 统计任务调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTaskStatHook (void) //统计任务钩子函数
{
#if OS_APP_HOOKS_EN > 0uApp_TaskStatHook();
#endif
}
#endif
9. 任务堆结构初始化函数
c语言的函数运行需要栈来支持,局部变量就是栈这种数据结构来实现的。栈其实就是os管理内存的一种方式,os是通过栈指针sp来管理栈内存的。在单片机裸机程序中,整个程序使用一个栈,这个栈是跟main共用的栈。在os中则不一样,因为os中有任务的概念,任务在宏观上实现并行,需要现场的保护和恢复,所以不同的任务就不能共用栈。每个任务都要自己的私有栈。
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{OS_STK *stk;(void)opt; /* 'opt' 并没有用到,防止编译器提示警告 */stk = ptos; /* 加载栈指针 *///发生中断后,xPSR, PC, LR, R12, R3-R0被自动保存在栈中 *(stk) = (INT32U)0x01000000uL; /* xPSR */*(--stk) = (INT32U)task; /* Entry Point(任务的入口) */*(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) */*(--stk) = (INT32U)0x12121212uL; /* R12 */*(--stk) = (INT32U)0x03030303uL; /* R3 */*(--stk) = (INT32U)0x02020202uL; /* R2 */*(--stk) = (INT32U)0x01010101uL; /* R1 */*(--stk) = (INT32U)p_arg; /* R0 : 变量 *//* 剩下的寄存器需要手动保存在堆栈 */ *(--stk) = (INT32U)0x11111111uL; /* R11 */*(--stk) = (INT32U)0x10101010uL; /* R10 */*(--stk) = (INT32U)0x09090909uL; /* R9 */*(--stk) = (INT32U)0x08080808uL; /* R8 */*(--stk) = (INT32U)0x07070707uL; /* R7 */*(--stk) = (INT32U)0x06060606uL; /* R6 */*(--stk) = (INT32U)0x05050505uL; /* R5 */*(--stk) = (INT32U)0x04040404uL; /* R4 */return (stk);
}
OSTaskStkInit()的作用就是对任务的栈内存进行初始化,我们每创建一个任务,都应该调用这个函数对任务的私有栈进行初始化,之后再去使用。
参数1: 指向任务的执行代码
参数2: 传给任务的调用时的参数
参数3: ptos指向栈顶
ARM是满降栈,也就是sp指针指向的内容都是满的,但是一开始ptos指向的是栈的最上方,而刚开始的时候该位置肯定为空,所以ptos指向的是”free”的。
参数4: 可选项,起到改变函数行为的效果,这是用于扩展的。但是uCOS-II暂时没用到。
在CM3内核中,函数发生中断后,xPSR,PC,LR,R12,R3-R0会被自动保存到栈中,R11-R4如果需要保存,需要手动保存。OSTaskStkInit()既然是在初始化这份栈,所以需要模拟被中断后的样子。代码中,R1-R12、R4-R11都没什么意义,目的在于方便调试,但是,
(1) xPSR=0x01000000L,xPSR的T位(第24位)置1,否则第一次执行任务时就Fault
(2) PC必须指向任务入口
(3) R14=任务返回函数
(4) R0用于传递任务的参数,等于p_arg
10. 切换任务时被调用的钩子函数
#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
void OSTaskSwHook (void) //切换任务时被调用的钩子函数
{
#if OS_APP_HOOKS_EN > 0u //如果有定义应用任务App_TaskSwHook(); //应用任务切换调用的钩子函数
#endif
}
#endif
11. 初始任务控制块化时调用的钩子函数
#if OS_CPU_HOOKS_EN > 0u
void OSTCBInitHook (OS_TCB *ptcb) //初始任务控制块化时调用的钩子函数
{
#if OS_APP_HOOKS_EN > 0uApp_TCBInitHook(ptcb);
#else(void)ptcb;
#endif
}
#endif
TCB即Task Control Block,任务控制块,记录了系统中每个任务的状态、属性信息。
12. 时钟节拍到了以后调用的钩子函数
#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u)
void OSTimeTickHook (void)
{
#if OS_APP_HOOKS_EN > 0uApp_TimeTickHook(); //应用程序的时钟节拍钩子函数
#endif#if OS_TMR_EN > 0u //如果有启动定时器管理OSTmrCtr++; //计时全局变量OSTmrCtr自加1//如果时间到了if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {OSTmrCtr = 0; //计时清零OSTmrSignal(); //发送信号量OSTmrSignal(初始值为0)//以便软件定时器扫面任务OSTmr-Task能请求到信号量继续运行}
#endif
}
#endif
13. SysTick超时后执行的函数
void OS_CPU_SysTickHandler (void)
{/* 进入临界区,OSIntNesting是全局变量,操作该变量时希望不被中断打扰 */OS_CPU_SR cpu_sr;OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */OSIntNesting++;/* 退出临界区 */OS_EXIT_CRITICAL();OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
}
14. 初始化SysTick定时器
void OS_CPU_SysTickInit (INT32U cnts)
{//使能SysTick定时器OS_CPU_CM3_NVIC_ST_RELOAD = cnts - 1u;/* Set prio of SysTick handler to min prio. *///使能SysTick定时器中断OS_CPU_CM3_NVIC_PRIO_ST = OS_CPU_CM3_NVIC_PRIO_MIN;/* Enable timer. */OS_CPU_CM3_NVIC_ST_CTRL |= OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC | OS_CPU_CM3_NVIC_ST_CTRL_ENABLE;/* Enable timer interrupt. */OS_CPU_CM3_NVIC_ST_CTRL |= OS_CPU_CM3_NVIC_ST_CTRL_INTEN;
}
OS_CPU_SysTickInit会被第一个任务调用,用于初始化SysTick定时器。
OS_CPU_SysTickHandler(void)和OS_CPU_SysTickInit (INT32U cnts)在移植的时候,我们会注释掉,取而代之的是STM32标准外设库的函数。
在本文件中,涉及到任务的很多概念,如TCB任务控制块、任务调度、统计/空闲任务等,这些将在下来的文章中介绍。
os_cpu_c.c相关推荐
- 启动之OS_CPU_C
任务堆栈结构的初始化 在uC/OS-II中,任务是一个无限循环,任务之间也不会互相调用,但是uC/OS-II总是执行优先级最高的任务,假定当前有一个更高优先级的任务进入就绪状态,为了保证原来低优先级任 ...
- 使用bc45编译ucos-II的配置过程
1.将ucos_ii的源代码解压到c盘根目录下形成SOFTWARE文件夹(使用网上盛传的压缩文件SOFTWARE.RAR) 2.将bc45安装在c盘根目录下,形成bc45文件夹,从别的地方复制tasm ...
- RTOS之uCOS-II源码下载及源码目录结构、常见的RTOS!
RTOS有众多种,用得最火的是FreeRTOS,因为它即使用于商业途径,也是开源免费的:其次是就是uCOS-II和uCOS-III.uCOS-II用于商业途径是需要付费的,但是对于学习研究却是免费的. ...
- ARM学习方法大杂烩,高手经验之谈,内容完全来自互联网
一步一步学习uCOS和ARM体系结构的心得 学习必备条件: 1.一块开发板--例如44B0开发板,建议初学者不要去购买那些ARM9体系结构的,因为作为初学者来说ARM9体系的东西是很复杂的,买块ARM ...
- STM32迷你板UCOSII系统移植
写在前面: 所需要下载的UCOSII代码链接:https://pan.baidu.com/s/1D_IyXhODEa5oVUdDv-GJrQ 提取码:mte3 本文结构 1.UCOSII简介 2.UC ...
- μC/OS-I移植需要编写的文件
移植μC/OS-II到一个新的体系结构上需要提供2个或3个文件: OS_CPU.H(C语言头文件) OS_CPU_C.C(C程序源文件) OS_CPU_A.ASM(汇编程序源文件) 移植代码包括的内容 ...
- UCOS 操作系统 安装配置环境
一.下载Borland C++ 4.5或Borland C++ 5.0和Turbo Assembler 5.0(TASM 5.0) 二.安装Borland C++ 4.5/5.0(我的安装在C:/BC ...
- μC-/OS II(一) PC编译环境的搭建
这个系列博文是关于对<嵌入式实时操作系统 μC-/OS II>(第二版)的学习笔记 μC-/OS II (一) PC编译器环境的搭建 1.关于编译器 采用Borland C++ 4.5作 ...
- uCOS-II中的OS_CPU.h,OS_CPU_A.s,OS_CPU.c
μC/OS-Ⅱ的移植集中在OS_CPU.h,OS_CPU_A.s,OS_CPU.c这三个文件上,下面分别详细介绍三个文件中的函数和需要修改或者编写的代码. 1. OS_CPU.h的移植 该文件定义了和 ...
最新文章
- php 会话控制 文件上传
- 详细讲解在Spring中进行集成测试AbstractDependencyInjectionSpringContextTests
- 无法定位程序输入点dxgiget_美国ABB TZIDC 智能定位器调试方法
- (二十七)【2021 WWW】Learning Intents behind Interactions with Knowledge Graph for Recommendation
- 黄冈中学首页布局(自己做的)
- Android学习笔记(二)——TextView常用属性以及下划线、跑马灯设置
- bmp转YUV RGB转YUV HM学习
- java IO 超详细讲解
- JQuery常用属性整理
- QML入门教程(1): Qt Quick与QML介绍
- SAT写作例子之Frank Lloyd Wright
- [大洋] Unity3D架构系列之- FSM有限状态机设计一至四
- android实现vr 功能,VR模式成亮点:属于Android N的10大新功能
- 不一样的课程表,不一样的Excle--用Excle进行设计(12):网状结构
- vue将链接转为二维码的方法即插件
- Windows11系统下Edge如何兼容IE浏览器
- [配置文件]_start.wzd
- 远程监控tomcat运行
- Mac电脑使用:下载安装SourceTree的步骤以及使用方法
- 有关于python的论文_有关python的论文
热门文章
- 【Python】记录抓包分析自动领取芝麻HTTP每日免费IP(成品+教程)
- macOS如何查看pdm文件
- MySQL使用gpfs共享磁盘_GPFS文件系统笔记
- Python游戏开发,Python实现童年小游戏推箱子 附带源码
- 数据仓库——数据采集与同步【系统埋点设计】
- java bll dal_C#中三层架构UI、BLL、DAL、Model实际操作
- 高德地图:实现3D模型轨迹回放效果(类似百度地图汽车模型路书)
- 动态规划算法之资源分配问题及其空间优化方案
- MATLAB | 入门——学习笔记
- LUT预设KREATIV WEDDING LUTS VOL4