From c0d1d0c1012646fd7f631efd0209f1eb1eb061c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 3 Mar 2014 17:37:40 +0700 Subject: rename port.c for different cortex --> able to add them in keil uvision --- .../Source/portable/RVDS/ARM_CM0/port_cm0.c | 397 +++++++++++++++ .../Source/portable/RVDS/ARM_CM0/port_m0.c | 397 --------------- .../freertos/Source/portable/RVDS/ARM_CM3/port.c | 487 ------------------ .../Source/portable/RVDS/ARM_CM3/port_cm3.c | 487 ++++++++++++++++++ .../freertos/Source/portable/RVDS/ARM_CM4F/port.c | 550 --------------------- .../Source/portable/RVDS/ARM_CM4F/port_cm4f.c | 550 +++++++++++++++++++++ 6 files changed, 1434 insertions(+), 1434 deletions(-) create mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_cm0.c delete mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_m0.c delete mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port.c create mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port_cm3.c delete mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port.c create mode 100644 vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port_cm4f.c diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_cm0.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_cm0.c new file mode 100644 index 000000000..cf898aa29 --- /dev/null +++ b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_cm0.c @@ -0,0 +1,397 @@ +/* + FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. + + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool. + + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under + the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also + provide a safety engineered and independently SIL3 certified version under + the SafeRTOS brand: http://www.SafeRTOS.com. +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM0 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) +#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) +#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) +#define portNVIC_SYSTICK_CLK 0x00000004 +#define portNVIC_SYSTICK_INT 0x00000002 +#define portNVIC_SYSTICK_ENABLE 0x00000001 +#define portNVIC_PENDSVSET 0x10000000 +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +#if configUSE_CUSTOM_TICK == 0 +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ); +#endif + +#ifdef __GNUC__ +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void vPortStartFirstTask( void ) __attribute__ (( naked )); +#endif + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack -= 6; /* LR, R12, R3..R1 */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11..R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ +#if defined ( __CC_ARM ) +__asm void vPortSVCHandler( void ) +{ + extern pxCurrentTCB; + + PRESERVE8 + + ldr r3, =pxCurrentTCB /* Restore the context. */ + ldr r1, [r3] /* Get the pxCurrentTCB address. */ + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + adds r0, r0, #16 /* Move to the high registers. */ + ldmia r0!, {r4-r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + msr psp, r0 /* Remember the new top of stack for the task. */ + subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */ + ldmia r0!, {r4-r7} /* Pop low registers. */ + mov r1, r14 + movs r0, #0xd + orrs r1, r0 + bx r1 +} + +#elif defined ( __GNUC__ ) +void vPortSVCHandler( void ) +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " add r0, r0, #16 \n" /* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ + " mov r8, r4 \n" + " mov r9, r5 \n" + " mov r10, r6 \n" + " mov r11, r7 \n" + " \n" + " msr psp, r0 \n" /* Remember the new top of stack for the task. */ + " \n" + " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ + " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ + " mov r1, r14 \n" /* OR R14 with 0x0d. */ + " movs r0, #0x0d \n" + " orr r1, r0 \n" + " bx r1 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +#else +#error vPortSVCHandler not defined for this compiler! +#endif +/*-----------------------------------------------------------*/ + +#if defined ( __CC_ARM ) +__asm void vPortStartFirstTask( void ) +{ + PRESERVE8 + + movs r0, #0x00 /* Locate the top of stack. */ + ldr r0, [r0] + msr msp, r0 /* Set the msp back to the start of the stack. */ + cpsie i /* Globally enable interrupts. */ + svc 0 /* System call to start first task. */ + nop +} + +#elif defined ( __GNUC__ ) +void vPortStartFirstTask( void ) +{ + __asm volatile( + " movs r0, #0x00 \n" /* Locate the top of stack. */ + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +#endif +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + +#if configUSE_CUSTOM_TICK == 0 + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); +#endif + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM0 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYieldFromISR( void ) +{ + /* Set a PendSV to request a context switch. */ + *( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET; +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +#if defined ( __CC_ARM ) +__asm void xPortPendSVHandler( void ) +{ + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + subs r0, r0, #32 /* Make space for the remaining low registers. */ + str r0, [r2] /* Save the new top of stack. */ + stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */ + mov r4, r8 /* Store the high registers. */ + mov r5, r9 + mov r6, r10 + mov r7, r11 + stmia r0!, {r4-r7} + push {r3, r14} + cpsid i + bl vTaskSwitchContext + cpsie i + pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */ + ldr r1, [r2] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + adds r0, r0, #16 /* Move to the high registers. */ + ldmia r0!, {r4-r7} /* Pop the high registers. */ + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + msr psp, r0 /* Remember the new top of stack for the task. */ + subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */ + ldmia r0!, {r4-r7} /* Pop low registers. */ + bx r3 +} + +#elif defined ( __GNUC__ ) +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " sub r0, r0, #32 \n" /* Make space for the remaining low registers. */ + " str r0, [r2] \n" /* Save the new top of stack. */ + " stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ + " mov r4, r8 \n" /* Store the high registers. */ + " mov r5, r9 \n" + " mov r6, r10 \n" + " mov r7, r11 \n" + " stmia r0!, {r4-r7} \n" + " \n" + " push {r3, r14} \n" + " cpsid i \n" + " bl vTaskSwitchContext \n" + " cpsie i \n" + " pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */ + " \n" + " ldr r1, [r2] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " add r0, r0, #16 \n" /* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ + " mov r8, r4 \n" + " mov r9, r5 \n" + " mov r10, r6 \n" + " mov r11, r7 \n" + " \n" + " msr psp, r0 \n" /* Remember the new top of stack for the task. */ + " \n" + " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ + " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ + " \n" + " bx r3 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB " + ); +} +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_CUSTOM_TICK == 0 +void xPortSysTickHandler( void ) +{ +unsigned long ulDummy; + + /* If using preemption, also force a context switch. */ + #if configUSE_PREEMPTION == 1 + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + #endif + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + vTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +#endif +/*-----------------------------------------------------------*/ + diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_m0.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_m0.c deleted file mode 100644 index cf898aa29..000000000 --- a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM0/port_m0.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT - http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - *************************************************************************** - * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * - * * - * http://www.FreeRTOS.org/FAQHelp.html * - * * - *************************************************************************** - - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool. - - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under - the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under - the SafeRTOS brand: http://www.SafeRTOS.com. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM0 port. - *----------------------------------------------------------*/ - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) -#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) -#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) -#define portNVIC_SYSTICK_CLK 0x00000004 -#define portNVIC_SYSTICK_INT 0x00000002 -#define portNVIC_SYSTICK_ENABLE 0x00000001 -#define portNVIC_PENDSVSET 0x10000000 -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) -#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) - -/* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) - -/* Each task maintains its own interrupt status in the critical nesting -variable. */ -static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; - -#if configUSE_CUSTOM_TICK == 0 -/* - * Setup the timer to generate the tick interrupts. - */ -static void prvSetupTimerInterrupt( void ); -#endif - -#ifdef __GNUC__ -/* - * Exception handlers. - */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__ (( naked )); -/* - * Start first task is a separate function so it can be tested in isolation. - */ -static void vPortStartFirstTask( void ) __attribute__ (( naked )); -#endif - -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch - interrupt. */ - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ - pxTopOfStack -= 6; /* LR, R12, R3..R1 */ - *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11..R4. */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ -#if defined ( __CC_ARM ) -__asm void vPortSVCHandler( void ) -{ - extern pxCurrentTCB; - - PRESERVE8 - - ldr r3, =pxCurrentTCB /* Restore the context. */ - ldr r1, [r3] /* Get the pxCurrentTCB address. */ - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - adds r0, r0, #16 /* Move to the high registers. */ - ldmia r0!, {r4-r7} - mov r8, r4 - mov r9, r5 - mov r10, r6 - mov r11, r7 - msr psp, r0 /* Remember the new top of stack for the task. */ - subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */ - ldmia r0!, {r4-r7} /* Pop low registers. */ - mov r1, r14 - movs r0, #0xd - orrs r1, r0 - bx r1 -} - -#elif defined ( __GNUC__ ) -void vPortSVCHandler( void ) -{ - __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " add r0, r0, #16 \n" /* Move to the high registers. */ - " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ - " mov r8, r4 \n" - " mov r9, r5 \n" - " mov r10, r6 \n" - " mov r11, r7 \n" - " \n" - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " \n" - " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ - " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ - " mov r1, r14 \n" /* OR R14 with 0x0d. */ - " movs r0, #0x0d \n" - " orr r1, r0 \n" - " bx r1 \n" - " \n" - " .align 2 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); -} -#else -#error vPortSVCHandler not defined for this compiler! -#endif -/*-----------------------------------------------------------*/ - -#if defined ( __CC_ARM ) -__asm void vPortStartFirstTask( void ) -{ - PRESERVE8 - - movs r0, #0x00 /* Locate the top of stack. */ - ldr r0, [r0] - msr msp, r0 /* Set the msp back to the start of the stack. */ - cpsie i /* Globally enable interrupts. */ - svc 0 /* System call to start first task. */ - nop -} - -#elif defined ( __GNUC__ ) -void vPortStartFirstTask( void ) -{ - __asm volatile( - " movs r0, #0x00 \n" /* Locate the top of stack. */ - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " svc 0 \n" /* System call to start first task. */ - " nop \n" - ); -} -#endif -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ - /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ - *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; - *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; - -#if configUSE_CUSTOM_TICK == 0 - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); -#endif - - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortStartFirstTask(); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the CM0 port will require this function as there - is nothing to return to. */ -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Set a PendSV to request a context switch. */ - *( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -#if defined ( __CC_ARM ) -__asm void xPortPendSVHandler( void ) -{ - extern pxCurrentTCB; - extern vTaskSwitchContext; - - PRESERVE8 - - mrs r0, psp - ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ - ldr r2, [r3] - subs r0, r0, #32 /* Make space for the remaining low registers. */ - str r0, [r2] /* Save the new top of stack. */ - stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */ - mov r4, r8 /* Store the high registers. */ - mov r5, r9 - mov r6, r10 - mov r7, r11 - stmia r0!, {r4-r7} - push {r3, r14} - cpsid i - bl vTaskSwitchContext - cpsie i - pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */ - ldr r1, [r2] - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - adds r0, r0, #16 /* Move to the high registers. */ - ldmia r0!, {r4-r7} /* Pop the high registers. */ - mov r8, r4 - mov r9, r5 - mov r10, r6 - mov r11, r7 - msr psp, r0 /* Remember the new top of stack for the task. */ - subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */ - ldmia r0!, {r4-r7} /* Pop low registers. */ - bx r3 -} - -#elif defined ( __GNUC__ ) -void xPortPendSVHandler( void ) -{ - /* This is a naked function. */ - - __asm volatile - ( - " mrs r0, psp \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " sub r0, r0, #32 \n" /* Make space for the remaining low registers. */ - " str r0, [r2] \n" /* Save the new top of stack. */ - " stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ - " mov r4, r8 \n" /* Store the high registers. */ - " mov r5, r9 \n" - " mov r6, r10 \n" - " mov r7, r11 \n" - " stmia r0!, {r4-r7} \n" - " \n" - " push {r3, r14} \n" - " cpsid i \n" - " bl vTaskSwitchContext \n" - " cpsie i \n" - " pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */ - " \n" - " ldr r1, [r2] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " add r0, r0, #16 \n" /* Move to the high registers. */ - " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ - " mov r8, r4 \n" - " mov r9, r5 \n" - " mov r10, r6 \n" - " mov r11, r7 \n" - " \n" - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " \n" - " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ - " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ - " \n" - " bx r3 \n" - " \n" - " .align 2 \n" - "pxCurrentTCBConst: .word pxCurrentTCB " - ); -} -#endif -/*-----------------------------------------------------------*/ - -#if configUSE_CUSTOM_TICK == 0 -void xPortSysTickHandler( void ) -{ -unsigned long ulDummy; - - /* If using preemption, also force a context switch. */ - #if configUSE_PREEMPTION == 1 - *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; - #endif - - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); - { - vTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ - /* Configure SysTick to interrupt at the requested rate. */ - *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; -} -#endif -/*-----------------------------------------------------------*/ - diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port.c deleted file mode 100644 index 4bbdeade1..000000000 --- a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT - http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - *************************************************************************** - * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * - * * - * http://www.FreeRTOS.org/FAQHelp.html * - * * - *************************************************************************** - - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool. - - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under - the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under - the SafeRTOS brand: http://www.SafeRTOS.com. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM3 port. - *----------------------------------------------------------*/ - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -#ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 255 -#endif - -#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 - #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html -#endif - -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ -#endif - -/* The __weak attribute does not work as you might expect with the Keil tools -so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if -the application writer wants to provide their own implementation of -vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION -is defined. */ -#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION - #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 -#endif - -/* Constants required to manipulate the core. Registers first... */ -#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) -#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) ) -#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) -/* ...then bits in the registers. */ -#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) -#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) -#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) - -#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) -#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) - -/* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) - -/* Each task maintains its own interrupt status in the critical nesting -variable. */ -static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; - -/* - * Setup the timer to generate the tick interrupts. The implementation in this - * file is weak to allow application writers to change the timer used to - * generate the tick interrupt. - */ -void vPortSetupTimerInterrupt( void ); - -/* - * Exception handlers. - */ -void xPortPendSVHandler( void ); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -static void prvStartFirstTask( void ); - -/*-----------------------------------------------------------*/ - -/* - * The number of SysTick increments that make up one tick period. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long ulTimerReloadValueForOneTick = 0; -#endif - -/* - * The maximum number of tick periods that can be suppressed is limited by the - * 24 bit resolution of the SysTick timer. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long xMaximumPossibleSuppressedTicks = 0; -#endif /* configUSE_TICKLESS_IDLE */ - -/* - * Compensate for the CPU cycles that pass while the SysTick is stopped (low - * power functionality only. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ - -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch - interrupt. */ - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -__asm void vPortSVCHandler( void ) -{ - PRESERVE8 - - ldr r3, =pxCurrentTCB /* Restore the context. */ - ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - msr psp, r0 /* Restore the task stack pointer. */ - mov r0, #0 - msr basepri, r0 - orr r14, #0xd - bx r14 -} -/*-----------------------------------------------------------*/ - -__asm void prvStartFirstTask( void ) -{ - PRESERVE8 - - /* Use the NVIC offset register to locate the stack. */ - ldr r0, =0xE000ED08 - ldr r0, [r0] - ldr r0, [r0] - /* Set the msp back to the start of the stack. */ - msr msp, r0 - /* Globally enable interrupts. */ - cpsie i - /* Call SVC to start the first task. */ - svc 0 - nop -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ - /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ - portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); - - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - prvStartFirstTask(); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the CM3 port will require this function as there - is nothing to return to. */ -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Set a PendSV to request a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -__asm void xPortPendSVHandler( void ) -{ - extern uxCriticalNesting; - extern pxCurrentTCB; - extern vTaskSwitchContext; - - PRESERVE8 - - mrs r0, psp - - ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ - ldr r2, [r3] - - stmdb r0!, {r4-r11} /* Save the remaining registers. */ - str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ - - stmdb sp!, {r3, r14} - mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r0 - bl vTaskSwitchContext - mov r0, #0 - msr basepri, r0 - ldmia sp!, {r3, r14} - - ldr r1, [r3] - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ - msr psp, r0 - bx r14 - nop -} -/*-----------------------------------------------------------*/ - -void xPortSysTickHandler( void ) -{ - #if configUSE_PREEMPTION == 1 - { - /* If using preemption, also force a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - #endif - - /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to - 1. If it is set to 0 tickless idle is not being used. If it is set to a - value other than 0 or 1 then a timer other than the SysTick is being used - to generate the tick interrupt. */ - #if configUSE_TICKLESS_IDLE == 1 - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; - #endif - - ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); - { - vTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); -} -/*-----------------------------------------------------------*/ - -#if configUSE_TICKLESS_IDLE == 1 - - __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) - { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Calculate the reload value required to wait xExpectedIdleTime - tick periods. -1 is used because this code will execute part way - through one of the tick periods, and the fraction of a tick period is - accounted for later. */ - ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) ); - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Stop the SysTick momentarily. The time the SysTick is stopped for - is accounted for as best it can be, but using the tickless mode will - inevitably result in some tiny drift of the time maintained by the - kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; - - /* If a context switch is pending then abandon the low power entry as - the context switch might have been pended by an external interrupt that - requires processing. */ - if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 ) - { - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - } - else - { - /* Adjust the reload value to take into account that the current - time slice is already partially complete. */ - ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) ); - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); - if( xExpectedIdleTime > 0 ) - { - __wfi(); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Stop SysTick. Again, the time the SysTick is stopped for is - accounted for as best it can be, but using the tickless mode will - inevitably result in some tiny drift of the time maintained by the - kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; - - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - /* The tick interrupt has already executed, and the SysTick - count reloaded with the portNVIC_SYSTICK_LOAD_REG value. - Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of - this tick period. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* The tick interrupt handler will already have pended the tick - processing in the kernel. As the pending tick will be - processed as soon as this function exits, the tick value - maintained by the tick is stepped forward by one less than the - time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. - Work out how long the sleep lasted. */ - ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick; - - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG - again, then set portNVIC_SYSTICK_LOAD_REG back to its standard - value. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - - vTaskStepTick( ulCompleteTickPeriods ); - } - } - -#endif /* #if configUSE_TICKLESS_IDLE */ - -/*-----------------------------------------------------------*/ - -/* - * Setup the SysTick timer to generate the tick interrupts at the required - * frequency. - */ -#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 - - void vPortSetupTimerInterrupt( void ) - { - /* Calculate the constants required to configure the tick interrupt. */ - #if configUSE_TICKLESS_IDLE == 1 - { - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); - ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - } - -#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ -/*-----------------------------------------------------------*/ - -__asm unsigned long ulPortSetInterruptMask( void ) -{ - PRESERVE8 - - mrs r0, basepri - mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r1 - bx r14 -} -/*-----------------------------------------------------------*/ - -__asm void vPortClearInterruptMask( unsigned long ulNewMask ) -{ - PRESERVE8 - - msr basepri, r0 - bx r14 -} diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port_cm3.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port_cm3.c new file mode 100644 index 000000000..4bbdeade1 --- /dev/null +++ b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM3/port_cm3.c @@ -0,0 +1,487 @@ +/* + FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. + + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool. + + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under + the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also + provide a safety engineered and independently SIL3 certified version under + the SafeRTOS brand: http://www.SafeRTOS.com. +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) +#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) +#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + ldr r3, =pxCurrentTCB /* Restore the context. */ + ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + msr psp, r0 /* Restore the task stack pointer. */ + mov r0, #0 + msr basepri, r0 + orr r14, #0xd + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + /* Call SVC to start the first task. */ + svc 0 + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM3 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYieldFromISR( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ + msr psp, r0 + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + #if configUSE_PREEMPTION == 1 + { + /* If using preemption, also force a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + #endif + + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + #endif + + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + vTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) + { + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods, and the fraction of a tick period is + accounted for later. */ + ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + + /* If a context switch is pending then abandon the low power entry as + the context switch might have been pended by an external interrupt that + requires processing. */ + if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 ) + { + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + else + { + /* Adjust the reload value to take into account that the current + time slice is already partially complete. */ + ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) ); + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. */ + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __wfi(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + /* The tick interrupt has already executed, and the SysTick + count reloaded with the portNVIC_SYSTICK_LOAD_REG value. + Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted. */ + ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + vTaskStepTick( ulCompleteTickPeriods ); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm unsigned long ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( unsigned long ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port.c deleted file mode 100644 index ed071ff8d..000000000 --- a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT - http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - *************************************************************************** - * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * - * * - * http://www.FreeRTOS.org/FAQHelp.html * - * * - *************************************************************************** - - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool. - - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under - the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under - the SafeRTOS brand: http://www.SafeRTOS.com. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM4F port. - *----------------------------------------------------------*/ - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -#ifndef __TARGET_FPU_VFP - #error This port can only be used when the project options are configured to enable hardware floating point support. -#endif - -#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 - #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html -#endif - -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ -#endif - -/* The __weak attribute does not work as you might expect with the Keil tools -so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if -the application writer wants to provide their own implementation of -vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION -is defined. */ -#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION - #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 -#endif - -/* Constants required to manipulate the core. Registers first... */ -#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) -#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) ) -#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) -/* ...then bits in the registers. */ -#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) -#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) -#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) - -#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) -#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) - -/* Constants required to manipulate the VFP. */ -#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */ -#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) - -/* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) -#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) - -/* Each task maintains its own interrupt status in the critical nesting -variable. */ -static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; - -/* - * Setup the timer to generate the tick interrupts. The implementation in this - * file is weak to allow application writers to change the timer used to - * generate the tick interrupt. - */ -void vPortSetupTimerInterrupt( void ); - -/* - * Exception handlers. - */ -void xPortPendSVHandler( void ); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -static void prvStartFirstTask( void ); - -/* - * Functions defined in portasm.s to enable the VFP. - */ -static void prvEnableVFP( void ); -/*-----------------------------------------------------------*/ - -/* - * The number of SysTick increments that make up one tick period. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long ulTimerReloadValueForOneTick = 0; -#endif - -/* - * The maximum number of tick periods that can be suppressed is limited by the - * 24 bit resolution of the SysTick timer. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long xMaximumPossibleSuppressedTicks = 0; -#endif /* configUSE_TICKLESS_IDLE */ - -/* - * Compensate for the CPU cycles that pass while the SysTick is stopped (low - * power functionality only. - */ -#if configUSE_TICKLESS_IDLE == 1 - static unsigned long ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ - -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch - interrupt. */ - - /* Offset added to account for the way the MCU uses the stack on entry/exit - of interrupts, and to ensure alignment. */ - pxTopOfStack--; - - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = 0; /* LR */ - - /* Save code space by skipping register initialisation. */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ - - /* A save method is being used that requires each task to maintain its - own exec return value. */ - pxTopOfStack--; - *pxTopOfStack = portINITIAL_EXEC_RETURN; - - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -__asm void vPortSVCHandler( void ) -{ - PRESERVE8 - - /* Get the location of the current TCB. */ - ldr r3, =pxCurrentTCB - ldr r1, [r3] - ldr r0, [r1] - /* Pop the core registers. */ - ldmia r0!, {r4-r11, r14} - msr psp, r0 - mov r0, #0 - msr basepri, r0 - bx r14 -} -/*-----------------------------------------------------------*/ - -__asm void prvStartFirstTask( void ) -{ - PRESERVE8 - - /* Use the NVIC offset register to locate the stack. */ - ldr r0, =0xE000ED08 - ldr r0, [r0] - ldr r0, [r0] - /* Set the msp back to the start of the stack. */ - msr msp, r0 - /* Globally enable interrupts. */ - cpsie i - /* Call SVC to start the first task. */ - svc 0 - nop -} -/*-----------------------------------------------------------*/ - -__asm void prvEnableVFP( void ) -{ - PRESERVE8 - - /* The FPU enable bits are in the CPACR. */ - ldr.w r0, =0xE000ED88 - ldr r1, [r0] - - /* Enable CP10 and CP11 coprocessors, then save back. */ - orr r1, r1, #( 0xf << 20 ) - str r1, [r0] - bx r14 - nop -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ - /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ - portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); - - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Ensure the VFP is enabled - it should be anyway. */ - prvEnableVFP(); - - /* Lazy save always. */ - *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - - /* Start the first task. */ - prvStartFirstTask(); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the CM4F port will require this function as there - is nothing to return to. */ -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Set a PendSV to request a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -__asm void xPortPendSVHandler( void ) -{ - extern uxCriticalNesting; - extern pxCurrentTCB; - extern vTaskSwitchContext; - - PRESERVE8 - - mrs r0, psp - - /* Get the location of the current TCB. */ - ldr r3, =pxCurrentTCB - ldr r2, [r3] - - /* Is the task using the FPU context? If so, push high vfp registers. */ - tst r14, #0x10 - it eq - vstmdbeq r0!, {s16-s31} - - /* Save the core registers. */ - stmdb r0!, {r4-r11, r14} - - /* Save the new top of stack into the first member of the TCB. */ - str r0, [r2] - - stmdb sp!, {r3, r14} - mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r0 - bl vTaskSwitchContext - mov r0, #0 - msr basepri, r0 - ldmia sp!, {r3, r14} - - /* The first item in pxCurrentTCB is the task top of stack. */ - ldr r1, [r3] - ldr r0, [r1] - - /* Pop the core registers. */ - ldmia r0!, {r4-r11, r14} - - /* Is the task using the FPU context? If so, pop the high vfp registers - too. */ - tst r14, #0x10 - it eq - vldmiaeq r0!, {s16-s31} - - msr psp, r0 - bx r14 - nop -} -/*-----------------------------------------------------------*/ - -void xPortSysTickHandler( void ) -{ - #if configUSE_PREEMPTION == 1 - { - /* If using preemption, also force a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - #endif - - /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to - 1. If it is set to 0 tickless idle is not being used. If it is set to a - value other than 0 or 1 then a timer other than the SysTick is being used - to generate the tick interrupt. */ - #if configUSE_TICKLESS_IDLE == 1 - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; - #endif - - ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); - { - vTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); -} -/*-----------------------------------------------------------*/ - -#if configUSE_TICKLESS_IDLE == 1 - - __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) - { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Calculate the reload value required to wait xExpectedIdleTime - tick periods. -1 is used because this code will execute part way - through one of the tick periods, and the fraction of a tick period is - accounted for later. */ - ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) ); - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Stop the SysTick momentarily. The time the SysTick is stopped for - is accounted for as best it can be, but using the tickless mode will - inevitably result in some tiny drift of the time maintained by the - kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; - - /* If a context switch is pending then abandon the low power entry as - the context switch might have been pended by an external interrupt that - requires processing. */ - if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 ) - { - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - } - else - { - /* Adjust the reload value to take into account that the current - time slice is already partially complete. */ - ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) ); - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); - if( xExpectedIdleTime > 0 ) - { - __wfi(); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Stop SysTick. Again, the time the SysTick is stopped for is - accounted for as best it can be, but using the tickless mode will - inevitably result in some tiny drift of the time maintained by the - kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; - - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - /* The tick interrupt has already executed, and the SysTick - count reloaded with the portNVIC_SYSTICK_LOAD_REG value. - Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of - this tick period. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* The tick interrupt handler will already have pended the tick - processing in the kernel. As the pending tick will be - processed as soon as this function exits, the tick value - maintained by the tick is stepped forward by one less than the - time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. - Work out how long the sleep lasted. */ - ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick; - - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG - again, then set portNVIC_SYSTICK_LOAD_REG back to its standard - value. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - - vTaskStepTick( ulCompleteTickPeriods ); - } - } - -#endif /* #if configUSE_TICKLESS_IDLE */ - -/*-----------------------------------------------------------*/ - -/* - * Setup the SysTick timer to generate the tick interrupts at the required - * frequency. - */ -#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 - - void vPortSetupTimerInterrupt( void ) - { - /* Calculate the constants required to configure the tick interrupt. */ - #if configUSE_TICKLESS_IDLE == 1 - { - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); - ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - } - -#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ -/*-----------------------------------------------------------*/ - -__asm unsigned long ulPortSetInterruptMask( void ) -{ - PRESERVE8 - - mrs r0, basepri - mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r1 - bx r14 -} -/*-----------------------------------------------------------*/ - -__asm void vPortClearInterruptMask( unsigned long ulNewMask ) -{ - PRESERVE8 - - msr basepri, r0 - bx r14 -} diff --git a/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port_cm4f.c b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port_cm4f.c new file mode 100644 index 000000000..ed071ff8d --- /dev/null +++ b/vendor/freertos/freertos/Source/portable/RVDS/ARM_CM4F/port_cm4f.c @@ -0,0 +1,550 @@ +/* + FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. + + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool. + + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under + the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also + provide a safety engineered and independently SIL3 certified version under + the SafeRTOS brand: http://www.SafeRTOS.com. +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __TARGET_FPU_VFP + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) +#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) +#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/* + * Functions defined in portasm.s to enable the VFP. + */ +static void prvEnableVFP( void ); +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + msr psp, r0 + mov r0, #0 + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + /* Call SVC to start the first task. */ + svc 0 + nop +} +/*-----------------------------------------------------------*/ + +__asm void prvEnableVFP( void ) +{ + PRESERVE8 + + /* The FPU enable bits are in the CPACR. */ + ldr.w r0, =0xE000ED88 + ldr r1, [r0] + + /* Enable CP10 and CP11 coprocessors, then save back. */ + orr r1, r1, #( 0xf << 20 ) + str r1, [r0] + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + prvEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM4F port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYieldFromISR( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r2, [r3] + + /* Is the task using the FPU context? If so, push high vfp registers. */ + tst r14, #0x10 + it eq + vstmdbeq r0!, {s16-s31} + + /* Save the core registers. */ + stmdb r0!, {r4-r11, r14} + + /* Save the new top of stack into the first member of the TCB. */ + str r0, [r2] + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + /* The first item in pxCurrentTCB is the task top of stack. */ + ldr r1, [r3] + ldr r0, [r1] + + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + + /* Is the task using the FPU context? If so, pop the high vfp registers + too. */ + tst r14, #0x10 + it eq + vldmiaeq r0!, {s16-s31} + + msr psp, r0 + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + #if configUSE_PREEMPTION == 1 + { + /* If using preemption, also force a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + #endif + + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + #endif + + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + vTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) + { + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods, and the fraction of a tick period is + accounted for later. */ + ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + + /* If a context switch is pending then abandon the low power entry as + the context switch might have been pended by an external interrupt that + requires processing. */ + if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 ) + { + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + else + { + /* Adjust the reload value to take into account that the current + time slice is already partially complete. */ + ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) ); + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. */ + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __wfi(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + /* The tick interrupt has already executed, and the SysTick + count reloaded with the portNVIC_SYSTICK_LOAD_REG value. + Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted. */ + ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + vTaskStepTick( ulCompleteTickPeriods ); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm unsigned long ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( unsigned long ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} -- cgit v1.3.1