-------------序言
手里有一个STM32F407的小板,于是想把ucos-III跑一下,之前在Freescale的kinetis K10上跑过ucos-III,于是直接把移植代码(官方的K53移植范例)拿过来,发现有问题,一运行就跑到hard_fault中断里了,一开始以为是堆栈啥的,检查了一遍没问题。于是根据Cortex-M3权威指南最后的查找硬件fault的做法,发现原因是总线fault上访造成的,然后一步步调试,发现是在时钟节拍任务里跑飞的:我只建了一个任务,而内核在时钟节拍里却检查到有多个任务,然后进行任务切换 ··· 换句话说,在任务切换后,我建立的任务的OS_TCB数据被破坏了,任务的名称也变了,寄存器的值也不是初始化的值。百思不得其解,网上搜了下,发现有人说使能FPU的话其寄存器在中断发生时也入栈。一看,果然,我在建立IAR的工程时在配置里使能了FPU。而目前ucos-III官方的移植都没有考虑到使能FPU的情况。于是翻看M4的手册,再修改移植代码,果然就对了!现在做个小结,也算是给自己的备忘。
------------------------------------------------------------------------------------------
首先,如下图所示,FPU有32个32位的单精度寄存器S0-S31,也可以组成16个64位的双精度寄存器D0-D15。
当使能FPU的时候,中断入栈如下:其中第一个不知道是啥,没有名字,第二个是FPU的状态控制寄存器,后面是S15到S0,接下来才是和M3一样的入栈。如果没有使能FPU,那么入栈也和M3一样。
再看一下STM32驱动库的初始化函数SystemInit(void),里面第一行如下:
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
__FPU_PRESENT是在stm32f4xx.h里定义的,代表该型号带有FPU;__FPU_USED应该是对应工程配置属性里的是否使能FPU。如果使能,则在此进行初始化。因为复位后默认FPU是不使能的。
根据前面的讨论,几个移植过程中设计入栈出栈的函数应修改。首先是堆栈初始化函数:
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
void *p_arg,
CPU_STK *p_stk_base,
CPU_STK *p_stk_limit,
CPU_STK_SIZE stk_size,
OS_OPT opt)
{
CPU_STK *p_stk;
(void)opt; /* Prevent compiler warning */
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception