summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-10-22 09:50:20 +0000
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-10-22 09:50:20 +0000
commite4f4e117093a2c1db7a7a732aa21ccb19588998e (patch)
treebe556754f43d3424e5d13b4c4d0dd6cb01d57842
parentd9b3f09da4ed662cd08f8e2812588ba0e1fbd599 (diff)
downloadfreertos-e4f4e117093a2c1db7a7a732aa21ccb19588998e.tar.gz
Improve how the scheduler is started in the GCC Cortex-M0 port.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2070 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM0/port.c56
1 files changed, 23 insertions, 33 deletions
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
index b0c3402bd..7af19599e 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -110,7 +110,7 @@ static void prvSetupTimerInterrupt( void );
*/
void xPortPendSVHandler( void ) __attribute__ (( naked ));
void xPortSysTickHandler( void );
-void vPortSVCHandler( void ) __attribute__ (( naked ));
+void vPortSVCHandler( void );
/*
* Start first task is a separate function so it can be tested in isolation.
@@ -148,42 +148,21 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
- its caller as there is nothing to return to. If a task wants to exit it
+ its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
-
- Artificially force an assert() to be triggered if configASSERT() is
+
+ Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
- portDISABLE_INTERRUPTS();
+ portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
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"
- );
+ /* This function is no longer used, but returned for backward
+ compatibility. */
}
/*-----------------------------------------------------------*/
@@ -193,9 +172,20 @@ void vPortStartFirstTask( void )
table offset register that can be used to locate the initial stack value.
Not all M0 parts have the application vector table at address 0. */
__asm volatile(
- " cpsie i \n" /* Globally enable interrupts. */
- " svc 0 \n" /* System call to start first task. */
- " nop \n"
+ " ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
+ " ldr r3, [r2] \n"
+ " ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
+ " add r0, #32 \n" /* Discard everything up to r0. */
+ " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
+ " movs r0, #2 \n" /* Switch to the psp stack. */
+ " msr CONTROL, r0 \n"
+ " pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
+ " mov lr, r5 \n" /* lr is now in r5. */
+ " cpsie i \n" /* The first task has its context and interrupts can be enabled. */
+ " pop {pc} \n" /* Finally, pop the PC to jump to the user defined task code. */
+ " \n"
+ " .align 2 \n"
+ "pxCurrentTCBConst2: .word pxCurrentTCB "
);
}
/*-----------------------------------------------------------*/
@@ -281,7 +271,7 @@ void vClearInterruptMaskFromISR( unsigned long ulMask )
" msr PRIMASK, r0 \n"
" bx lr "
);
-
+
/* Just to avoid compiler warning. */
( void ) ulMask;
}