本帖最后由 Eric2013 于 2014-12-23 18:42 编辑
特别说明:
1. 本教程是安富莱电子原创。
2. 安富莱STM32F407开发板资料已经全部开源,开源地址:地址链接
3. 当前共配套300多个实例,4套用户手册。
第10章 μCOS-III在高版本MDK开启FPU方案
由于官方提供的μCOS-III移植工程中对于浮点寄存器的入栈和出栈处理是错误的,所以网上就流传了各种修正版本。但是这些修正的代码只能在MDK4.7以下版本中可以正常的运行,MDK4.7及其以上的版本无**常运行。本期教程为此而生。本期教程提供的方案只有任务使用了浮点寄存器(也就是做了浮点运算)才需要将其入栈,没有使用浮点寄存器的任务不需要进行入栈,认识到这点很重要。此方案在MDK4.54、4.73、5.10以及IAR6.3、6.7上面测试均通过。 10.1 官方移植方案 10.2 开启FPU解决方案 10.3 开启FPU的优劣 10.4 总结 10.1 官方移植方案 官方提供的移植工程里面,只有IAR工程里面才有浮点寄存器的入栈和出栈处理函数,MDK工程里面是没有的。下面这个是os_cpu_c.c文件夹中的函数: /*
*********************************************************************************************************
* INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
* stack frame of the task being created. This function is highly processor specific.
*
* Arguments : task is a pointer to the task code
*
* p_arg is a pointer to a user supplied data area that will be passed to the task
* when the task first executes.
*
* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
* of the stack.
*
* opt specifies options that can be used to alter the behavior of OSTaskStkInit().
* (see uCOS_II.H for OS_TASK_OPT_xxx).
*
* Returns : Always returns the location of the new top-of-stack once the processor registers have
* been placed on the stack in the proper order.
*
* Note(s) : (1) Interrupts are enabled when task starts executing.
*
* (2) All tasks run in Thread mode, using process stack.
*
* (3) There are two different stack frames depending on whether the Floating-Point(FP)
* co-processor is enabled or not.
*
* (a) The stack frame shown in the diagram is used when the FP co-processor is not present and
* OS_TASK_OPT_SAVE_FP is disabled. In this case, the FP registers and FP Status Control
* register are not saved in the stack frame.
*
* (b) If the FP co-processor is present but the OS_TASK_OPT_SAVE_FP is not set, then the stack
* frame is saved as shown in diagram (a). Moreover, if OS_TASK_OPT_SAVE_FP is set, then the
* FP registers and FP Status Control register are saved in the stack frame.
*
* (1) When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the
* Floating-Point Context Control Register (FPCCR).
*
* +------------+ +------------+ * | | | | * +------------+ +------------+ * | xPSR | | xPSR | * +------------+ +------------+ * |Return Addr| |Return Addr | * +------------+ +------------+ * | LR(R14) | | LR(R14) | * +------------+ +------------+ * | R12 | | R12 | * +------------+ +------------+ * | R3 | | R3 | * +------------+ +------------+ * | R2 | | R0 | * +------------+ +------------+ * | R1 | | R1 | * +------------+ +------------+ * | R0 | | R0 | * +------------+ +------------+ * | R11 | | R11 | * +------------+ +------------+ * | R10 | | R10 | * +------------+ +------------+ * | R9 | | R9 | * +------------+ +------------+ * | R8 | | R8 | * +------------+ +------------+ * | R7 | | R7 | * +------------+ +------------+ * | R6 | | R6 | * +------------+ +------------+ * | R5 | | R5 | * +------------+ +------------+ * | R4 | | R4 | * +------------+ +------------+ * (a) | FPSCR | * +------------+ * | S31 | * +------------+ * . * . * . * +------------+ * | S1 | +------------+ * | S0 | * +------------+ * (b) * * (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture
*
* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned
* on entry to AAPCS-Conforming functions states :
*
* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive
* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes).
* Doing otherwise creates more problems than it solves.
*
* In return for preserving the natural alignment of data, conforming code is permitted
* to rely on that alignment. To support aligning data allocated on the stack, the stack
* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In
* practice this requirement is met if:
*
* (1) At each call site, the current size of the calling function抯 stack frame is a multiple of 8 bytes.
* This places an obligation on compilers and assembly language programmers.
*
* (2) SP is a multiple of 8 when control first enters a program.
* This places an obligation on authors of low level OS, RTOS, and runtime library
* code to align SP at all points at which control first enters
* a body of (AAPCS-conforming) code.
*
* In turn, this requires the value of SP to be aligned to 0 modulo 8:
*
* (3) By exception handlers, before calling AAPCS-conforming code.
*
* (4) By OS/RTOS/run-time system code, before giving control to an application.
*
* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry
* to AAPCS-conforming functions advisory note also states.
*
* " This requirement extends to operating systems and run-time code for all architecture versions
* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations
* associated with ARMV7M are discussed in ?.3.3"
*
* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned
* to 8-byte boundaries to support legacy execution enviroments.
*
* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM
* architecture states : "The stack must also conform to the following
* constraint at a public interface:
*
* (1) SP mod 8 = 0. The stack must be double-word aligned"
*
* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment.
*
* "8 byte stack alignment is a requirement of the ARM Architecture Procedure
* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte
* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external
* interfaces. In practice this requirement is met if:
*
* (1) At each external interface, the current stack pointer
* is a multiple of 8 bytes.
*
* (2) Your OS maintains 8 byte stack alignment on its external interfaces
* e.g. on task switches"
*
**********************************************************************************************************
*/
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *p_stk;
p_stk = ptos + 1u; /* 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) = (OS_STK)0x01000000uL; /* xPSR */
*(--p_stk) = (OS_STK)task; /* Entry Point */
*(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */
*(--p_stk) = (OS_STK)0x12121212uL; /* R12 */
*(--p_stk) = (OS_STK)0x03030303uL; /* R3 */
*(--p_stk) = (OS_STK)0x02020202uL; /* R2 */
*(--p_stk) = (OS_STK)0x01010101uL; /* R1 */
*(--p_stk) = (OS_STK)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--p_stk) = (OS_STK)0x11111111uL; /* R11 */
*(--p_stk) = (OS_STK)0x10101010uL; /* R10 */
*(--p_stk) = (OS_STK)0x09090909uL; /* R9 */
*(--p_stk) = (OS_STK)0x08080808uL; /* R8 */
*(--p_stk) = (OS_STK)0x07070707uL; /* R7 */
*(--p_stk) = (OS_STK)0x06060606uL; /* R6 */
*(--p_stk) = (OS_STK)0x05050505uL; /* R5 */
*(--p_stk) = (OS_STK)0x04040404uL; /* R4 */
#if (OS_CPU_ARM_FP_EN > 0u)
if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
*--p_stk = (OS_STK)0x02000000u; /* FPSCR */
/* Initialize S0-S31 floating point registers */
*--p_stk = (OS_STK)0x41F80000u; /* S31 */
*--p_stk = (OS_STK)0x41F00000u; /* S30 */
*--p_stk = (OS_STK)0x41E80000u; /* S29 */
*--p_stk = (OS_STK)0x41E00000u; /* S28 */
*--p_stk = (OS_STK)0x41D80000u; /* S27 */
*--p_stk = (OS_STK)0x41D00000u; /* S26 */
*--p_stk = (OS_STK)0x41C80000u; /* S25 */
*--p_stk = (OS_STK)0x41C00000u; /* S24 */
*--p_stk = (OS_STK)0x41B80000u; /* S23 */
*--p_stk = (OS_STK)0x41B00000u; /* S22 */
*--p_stk = (OS_STK)0x41A80000u; /* S21 */
*--p_stk = (OS_STK)0x41A00000u; /* S20 */
*--p_stk = (OS_STK)0x41980000u; /* S19 */
*--p_stk = (OS_STK)0x41900000u; /* S18 */
*--p_stk = (OS_STK)0x41880000u; /* S17 */
*--p_stk = (OS_STK)0x41800000u; /* S16 */
*--p_stk = (OS_STK)0x41700000u; /* S15 */
*--p_stk = (OS_STK)0x41600000u; /* S14 */
*--p_stk = (OS_STK)0x41500000u; /* S13 */
*--p_stk = (OS_STK)0x41400000u; /* S12 */
*--p_stk = (OS_STK)0x41300000u; /* S11 */
*--p_stk = (OS_STK)0x41200000u; /* S10 */
*--p_stk = (OS_STK)0x41100000u; /* S9 */
*--p_stk = (OS_STK)0x41000000u; /* S8 */
*--p_stk = (OS_STK)0x40E00000u; /* S7 */
*--p_stk = (OS_STK)0x40C00000u; /* S6 */
*--p_stk = (OS_STK)0x40A00000u; /* S5 */
*--p_stk = (OS_STK)0x40800000u; /* S4 */
*--p_stk = (OS_STK)0x40400000u; /* S3 */
*--p_stk = (OS_STK)0x40000000u; /* S2 */
*--p_stk = (OS_STK)0x3F800000u; /* S1 */
*--p_stk = (OS_STK)0x00000000u; /* S0 */
}
#endif
return (p_stk);
}
|