1. Tick-UCOS心跳
UCOS需要通过SysTick定时器产生固定时长的系统内核调用OSTimeTick对所有任务延时减一,如果该任务并非由OSTaskSuspend挂起(即处于OS_Stat_Suspend),并且更新就绪表和就绪组的相应位,所以UCOS需要开启SysTick_Handler的中断异常服务。
①首先需要设置os_cpu_c.c中关于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. */
//可以查阅《Cortex-M3权威手册》-Ch8
#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. */
*********************************************************************************************************
* 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. */
//可以查阅《Cortex-M3权威手册》-Ch8
#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. */
②使用OS_CPU_SysTickInit(INT32U cnts)配置systick重装倒数数值以及中断优先级、中断使能位。
③OS_CPU_SysTickHandler()则为UCOS所需SysTick_Handler异常服务函数主体,将其让systick中断服务所调用。
void SysTick_Handler(void)
{
OS_CPU_SysTickHandler();
}
{
OS_CPU_SysTickHandler();
}
2. 中断服务进入和退出时需要调用的函数
在进入中断时,需要增加中断嵌套层数OSIntNesting以约束某些不允许在中断中运行的函数。
①首先调用OSIntEnter()增加中断嵌套层数。
②在中断服务退出时调用OSIntExit()减少中断嵌套层数,调用OS_SchedNew()计算当前已就绪任务最高优先级,并更新当前运行任务优先级,调用任务切换函数OS_TASK_SW()切换到其他任务。
3. 系统启动顺序
①关闭CPU外部中断(注意任务切换需要使用PendSV异常,SysTick异常可以关闭或者开启,因为在OSRunning为OS_FALSE时不会进行任务调度(即调用OSStart函数前)
②首先需要进行CPU设备初始化,比如RCC、GPIO、NVIC、EXIT等,修改NVIC时不应该打开中断。
③系统初始化OSInit(),创建空闲和统计任务
④配置SysTick定时器OS_CPU_SysTickInit()
⑤调用OSTaskCreate或OSTaskCreateExt创建所需任务
⑥启动CPU外部中断
⑦调用OSStart()开始运行就绪最高优先级任务,并更改OSRunning为OS_TRUE,此时会主动进入PendSV调用OSCtxSW切换任务。
4. PendSV服务优先级不能过高
当PendSV优先级过高时,将导致OSTimeDly函数运行产生硬件错误。
错误概况如下:
5. CM3堆栈地址向下生长
因为CM3堆栈生长方向是向下生长,所以OSTaskCreate时,堆栈地址赋值应指向分配堆栈大小的最后一个字单元(typedef unsigned int OS_STK;)。