μC/OS-II v2.92.11版本移植到STM32F103
之前用的都是μC/OS-III版本,这几天心血来潮尝试了下μC/OS-II的最新版移植到stm32f103的板子上,移植完毕后,板子可以正常跑,但是同事在调试的时候用printf函数打印浮点的时候却出错,仿真的时候浮点运算结果却是正常的,按照AAPCS规约,堆栈需要8字节对齐,查看同事的任务创建函数如下:
OSTaskCreate ( task_name, ( void* ) 0, ( OS_STK* ) & TASK_STK[STK_SIZE - 1], TASK_PRIO );
按照老版本的UcosII规则,直接在任务堆栈数组前用关键字__align(8)后打印便没有问题,但是实际情况在这个版本却行不通,打印还是错误……悲剧!
到os_cpu_c.c文件下查看任务函数堆栈初始化函数如下:
OS_STK *OSTaskStkInit ( void ( *task ) ( void *p_arg ), void *p_arg, OS_STK *ptos, INT16U opt ) { OS_STK *p_stk; ( void ) opt; /* 'opt' is not used, prevent warning */ p_stk = ptos; /* Load stack pointer */ /* Align the stack to 8-bytes. */ p_stk = ( OS_STK * ) ( ( OS_STK ) ( p_stk ) & 0xFFFFFFF8u ); /* Registers stacked as if auto-saved on exception */ * ( p_stk ) = ( INT32U ) 0x01000000uL; /* xPSR */ * ( --p_stk ) = ( INT32U ) task; /* Entry Point */ * ( --p_stk ) = ( INT32U ) OS_TaskReturn; /* R14 (LR) */ * ( --p_stk ) = ( INT32U ) 0x12121212uL; /* R12 */ * ( --p_stk ) = ( INT32U ) 0x03030303uL; /* R3 */ * ( --p_stk ) = ( INT32U ) 0x02020202uL; /* R2 */ * ( --p_stk ) = ( INT32U ) 0x01010101uL; /* R1 */ * ( --p_stk ) = ( INT32U ) p_arg; /* R0 : argument */ /* Remaining registers saved on process stack */ * ( --p_stk ) = ( INT32U ) 0x11111111uL; /* R11 */ * ( --p_stk ) = ( INT32U ) 0x10101010uL; /* R10 */ * ( --p_stk ) = ( INT32U ) 0x09090909uL; /* R9 */ * ( --p_stk ) = ( INT32U ) 0x08080808uL; /* R8 */ * ( --p_stk ) = ( INT32U ) 0x07070707uL; /* R7 */ * ( --p_stk ) = ( INT32U ) 0x06060606uL; /* R6 */ * ( --p_stk ) = ( INT32U ) 0x05050505uL; /* R5 */ * ( --p_stk ) = ( INT32U ) 0x04040404uL; /* R4 */ return ( p_stk ); }
任务函数堆栈首地址已经是8字节对齐,但是看入栈后的地址却不是8字节对齐了,p_stk只自减了15次,最后的栈地址并不是8字节对齐;按照arm核入栈规则,栈地址先减去4后入栈,但是ucosII的入栈却是先入栈后减4,正确的任务创建方法应该是:
OSTaskCreate ( task_name, ( void* ) 0, ( OS_STK* ) & TASK_STK[STK_SIZE], TASK_PRIO );
任务函数堆栈初始化函数修改为:
OS_STK *OSTaskStkInit ( void ( *task ) ( void *p_arg ), void *p_arg, OS_STK *ptos, INT16U opt ) { OS_STK *p_stk; ( void ) opt; /* 'opt' is not used, prevent warning */ p_stk = ptos; /* Load stack pointer */ /* Align the stack to 8-bytes. */ p_stk = ( OS_STK * ) ( ( OS_STK ) ( p_stk ) & 0xFFFFFFF8u ); /* Registers stacked as if auto-saved on exception */ * ( --p_stk ) = ( INT32U ) 0x01000000uL; /* xPSR */ * ( --p_stk ) = ( INT32U ) task; /* Entry Point */ * ( --p_stk ) = ( INT32U ) OS_TaskReturn; /* R14 (LR) */ * ( --p_stk ) = ( INT32U ) 0x12121212uL; /* R12 */ * ( --p_stk ) = ( INT32U ) 0x03030303uL; /* R3 */ * ( --p_stk ) = ( INT32U ) 0x02020202uL; /* R2 */ * ( --p_stk ) = ( INT32U ) 0x01010101uL; /* R1 */ * ( --p_stk ) = ( INT32U ) p_arg; /* R0 : argument */ /* Remaining registers saved on process stack */ * ( --p_stk ) = ( INT32U ) 0x11111111uL; /* R11 */ * ( --p_stk ) = ( INT32U ) 0x10101010uL; /* R10 */ * ( --p_stk ) = ( INT32U ) 0x09090909uL; /* R9 */ * ( --p_stk ) = ( INT32U ) 0x08080808uL; /* R8 */ * ( --p_stk ) = ( INT32U ) 0x07070707uL; /* R7 */ * ( --p_stk ) = ( INT32U ) 0x06060606uL; /* R6 */ * ( --p_stk ) = ( INT32U ) 0x05050505uL; /* R5 */ * ( --p_stk ) = ( INT32U ) 0x04040404uL; /* R4 */ return ( p_stk ); }
最后打印float型数据,结果正确。