目的:看看ucos中SysTick的中断优先级配置情况。
关于 SysTick 定时器的 说明参见我的另一个文章。--STM32F10XXXX---SysTick滴答定时器
在系统启动多任务后的第一个任务TaskStart中(即调用过OSStart()函数后),
先初始化BSP(Board Support Package)板级支持包:
- 设定RCC(复位和实时时钟控制)外设,对系统时钟源进行设置
- 初始化系统驱动程序;
然后调用OS_CPU_SysTickInit()完成对系统Tick的设定。
先上程序:
os_cpu_c.c中的相关宏定义
/*
*********************************************************************************************************
* SYS TICK DEFINES
*********************************************************************************************************
*/
#define OS_CPU_CM3_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010)) /* SysTick Ctrl & Status Reg. */
#define OS_CPU_CM3_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014)) /* SysTick Reload Value Reg. */
#define OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018)) /* SysTick Current Value Reg. */
#define OS_CPU_CM3_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01C)) /* SysTick Cal Value Reg. *///SysTick校准值寄存器
#define OS_CPU_CM3_NVIC_ST_CTRL_COUNT 0x00010000 /* Count flag. */
#define OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC 0x00000004 /* Clock Source. */
#define OS_CPU_CM3_NVIC_ST_CTRL_INTEN 0x00000002 /* Interrupt enable. */
#define OS_CPU_CM3_NVIC_ST_CTRL_ENABLE 0x00000001 /* Counter mode. */
/*
*********************************************************************************************************
* OS_CPU_SysTickInit()
*
* Description: Initialize the SysTick.
*
* Arguments : none.
*
* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization.
*********************************************************************************************************
*/
void OS_CPU_SysTickInit (void)
{
INT32U cnts;
//通过已经设置的RCC_ClocksTypeDef的HCLK_Frequency时钟频率 如:72M
cnts = OS_CPU_SysTickClkFreq() / OS_TICKS_PER_SEC; //<span style="font-family: Arial, Helvetica, sans-serif;">OS_TICKS_PER_SEC设置为1000</span>
OS_CPU_CM3_NVIC_ST_RELOAD = (cnts - 1); //得到的值写入 Systick 重装载数值寄存器
/* 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;
}
上边的SysTick外设的宏定义中的注释可能有错误:
OS_CPU_CM3_NVIC_ST_CTRL_INTEN :SysTick一定是向下计数的模式,该位决定----当事件到来时,是否发出异常请求。
OS_CPU_CM3_NVIC_ST_CTRL_ENABLE:定时器使能。
OS_CPU_SysTickInit实现功能:
- SysTick自动重装载值寄存器 填充;
- SysTick控制状态寄存器设置:选择内核时钟(FCLK)、定时器使能、事件到达触发异常
SysTick异常处理程序:
/*
*********************************************************************************************************
* OS_CPU_SysTickHandler()
*
* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
* interrupt.
*
* Arguments : none.
*
* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
*********************************************************************************************************
*/
void OS_CPU_SysTickHandler (void)
{
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 */
}
先OSIntNesting++;Tell uC/OS-II我们正在开始一个ISR终端服务程序。
后OSTimeTick(); 目的是在时钟节拍到来时,检查每个任务的任务控制块中的.OSTCBDly-1后是否为0,如果是,那么表明这个任务刚才是挂起的状态,此时应改变为就绪态
最后是OSIntExit(); ---OS_SchedNew();调度发生
说说OSTimeTick();
任务状态图如下:
先弄几个宏定义
OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running */
#if OS_TICK_STEP_EN > 0
OS_EXT INT8U OSTickStepState; /* Indicates the state of the tick step feature */
#endif
/*
*********************************************************************************************************
* Values for OSTickStepState
*
* Note(s): This feature is used by uC/OS-View.
*********************************************************************************************************
*/
#if OS_TICK_STEP_EN > 0
#define OS_TICK_STEP_DIS 0u /* Stepping is disabled, tick runs as mormal */
#define OS_TICK_STEP_WAIT 1u /* Waiting for uC/OS-View to set OSTickStepState to _ONCE */
#define OS_TICK_STEP_ONCE 2u /* Process tick once and wait for next cmd from uC/OS-View */
#endif
#define OS_TASK_IDLE_PRIO (OS_LOWEST_PRIO) /* IDLE task priority
/*
*********************************************************************************************************
* TASK STATUS (Bit definition for OSTCBStat)
*********************************************************************************************************
*/
#define OS_STAT_RDY 0x00u /* Ready to run */
#define OS_STAT_SEM 0x01u /* Pending on semaphore */
#define OS_STAT_MBOX 0x02u /* Pending on mailbox */
#define OS_STAT_Q 0x04u /* Pending on queue */
#define OS_STAT_SUSPEND 0x08u /* Task is suspended */
#define OS_STAT_MUTEX 0x10u /* Pending on mutual exclusion semaphore */
#define OS_STAT_FLAG 0x20u /* Pending on event flag group */
#define OS_STAT_MULTI 0x80u /* Pending on multiple events */
#define OS_STAT_PEND_ANY (OS_STAT_SEM | OS_STAT_MBOX | OS_STAT_Q | OS_STAT_MUTEX | OS_STAT_FLAG)
/*
*********************************************************************************************************
* TASK PEND STATUS (Status codes for OSTCBStatPend)
*********************************************************************************************************
*/
#define OS_STAT_PEND_OK 0u /* Pending status OK, not pending, or pending complete */
#define OS_STAT_PEND_TO 1u /* Pending timed out */
#define OS_STAT_PEND_ABORT 2u /* Pending aborted */
OSTimeTick();
/*
*********************************************************************************************************
* PROCESS SYSTEM TICK
*
* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
* as a 'clock tick'). This function should be called by the ticker ISR but, can also be
* called by a high priority task.
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
void OSTimeTick (void)
{
OS_TCB *ptcb;
#if OS_TICK_STEP_EN > 0
BOOLEAN step;
#endif
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_TIME_TICK_HOOK_EN > 0
OSTimeTickHook(); /* Call user definable hook */
#endif
#if OS_TIME_GET_SET_EN > 0
OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */
OSTime++;
OS_EXIT_CRITICAL();
#endif
if (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0
switch (OSTickStepState) { /* Determine whether we need to process a tick */
case OS_TICK_STEP_DIS: /* Yes, stepping is disabled */
step = OS_TRUE;
break;
case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ... */
step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */
break;
case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */
step = OS_TRUE; /* ... step command from uC/OS-View */
OSTickStepState = OS_TICK_STEP_WAIT;
break;
default: /* Invalid case, correct situation */
step = OS_TRUE;
OSTickStepState = OS_TICK_STEP_DIS;
break;
}
if (step == OS_FALSE) { /* Return if waiting for step command */
return;
}
#endif
ptcb = OSTCBList; /* Point at first TCB in TCB list */
while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list//遍历 */
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0) { /* No, Delayed or waiting for event with TO */
if (--ptcb->OSTCBDly == 0) { /* Decrement nbr of ticks to end of delay */
/* Check for timeout */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {//不为就绪态,置成就绪态
ptcb->OSTCBStat &= ~(INT8U)OS_STAT_PEND_ANY; /* Yes, Clear status flag 就绪态OS_STAT_RDY */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout 挂起状态设置为挂起超时<span style="font-family: Arial, Helvetica, sans-serif;">OS_STAT_PEND_TO</span> */
} else {
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//否则挂起状态OK
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? 任务暂停? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready 不是暂停,将它就绪 */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
}
}
ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL();
}
}
}
OSIntExit();
---待续,,,,