]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
Improve how the scheduler is started in the GCC Cortex-M0 port.
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CM0 / port.c
index b0c3402bd0e3d90204c4820409963bc6b38d42ef..7af19599ea56bfcfc7c6b292e7437306ef95c188 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. \r
+    FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
@@ -110,7 +110,7 @@ static void prvSetupTimerInterrupt( void );
  */\r
 void xPortPendSVHandler( void ) __attribute__ (( naked ));\r
 void xPortSysTickHandler( void );\r
-void vPortSVCHandler( void ) __attribute__ (( naked ));\r
+void vPortSVCHandler( void );\r
 \r
 /*\r
  * Start first task is a separate function so it can be tested in isolation.\r
@@ -148,42 +148,21 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
 static void prvTaskExitError( void )\r
 {\r
        /* A function that implements a task must not exit or attempt to return to\r
-       its caller as there is nothing to return to.  If a task wants to exit it \r
+       its caller as there is nothing to return to.  If a task wants to exit it\r
        should instead call vTaskDelete( NULL ).\r
-       \r
-       Artificially force an assert() to be triggered if configASSERT() is \r
+\r
+       Artificially force an assert() to be triggered if configASSERT() is\r
        defined, then stop here so application writers can catch the error. */\r
        configASSERT( uxCriticalNesting == ~0UL );\r
-       portDISABLE_INTERRUPTS();       \r
+       portDISABLE_INTERRUPTS();\r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void vPortSVCHandler( void )\r
 {\r
-       __asm volatile (\r
-                                       "       ldr     r3, pxCurrentTCBConst2          \n" /* Restore the context. */\r
-                                       "       ldr r1, [r3]                                    \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */\r
-                                       "       ldr r0, [r1]                                    \n" /* The first item in pxCurrentTCB is the task top of stack. */\r
-                                       "       add r0, r0, #16                                 \n" /* Move to the high registers. */\r
-                                       "       ldmia r0!, {r4-r7}                              \n" /* Pop the high registers. */\r
-                                       "       mov r8, r4                                              \n"\r
-                                       "       mov r9, r5                                              \n"\r
-                                       "       mov r10, r6                                             \n"\r
-                                       "       mov r11, r7                                             \n"\r
-                                       "                                                                       \n"\r
-                                       "       msr psp, r0                                             \n" /* Remember the new top of stack for the task. */\r
-                                       "                                                                       \n"\r
-                                       "       sub r0, r0, #32                                 \n" /* Go back for the low registers that are not automatically restored. */\r
-                                       "       ldmia r0!, {r4-r7}              \n" /* Pop low registers.  */\r
-                                       "       mov r1, r14                                             \n" /* OR R14 with 0x0d. */\r
-                                       "       movs r0, #0x0d                                  \n"\r
-                                       "       orr r1, r0                                              \n"\r
-                                       "       bx r1                                                   \n"\r
-                                       "                                                                       \n"\r
-                                       "       .align 2                                                \n"\r
-                                       "pxCurrentTCBConst2: .word pxCurrentTCB \n"\r
-                               );\r
+       /* This function is no longer used, but returned for backward\r
+       compatibility. */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -193,9 +172,20 @@ void vPortStartFirstTask( void )
        table offset register that can be used to locate the initial stack value.\r
        Not all M0 parts have the application vector table at address 0. */\r
        __asm volatile(\r
-                                       " cpsie i                       \n" /* Globally enable interrupts. */\r
-                                       " svc 0                         \n" /* System call to start first task. */\r
-                                       " nop                           \n"\r
+       "       ldr     r2, pxCurrentTCBConst2  \n" /* Obtain location of pxCurrentTCB. */\r
+       "       ldr r3, [r2]                            \n"\r
+       "       ldr r0, [r3]                            \n" /* The first item in pxCurrentTCB is the task top of stack. */\r
+       "       add r0, #32                                     \n" /* Discard everything up to r0. */\r
+       "       msr psp, r0                                     \n" /* This is now the new top of stack to use in the task. */\r
+       "       movs r0, #2                                     \n" /* Switch to the psp stack. */\r
+       "       msr CONTROL, r0                         \n"\r
+       "       pop {r0-r5}                                     \n" /* Pop the registers that are saved automatically. */\r
+       "       mov lr, r5                                      \n" /* lr is now in r5. */\r
+       "       cpsie i                                         \n" /* The first task has its context and interrupts can be enabled. */\r
+       "       pop {pc}                                        \n" /* Finally, pop the PC to jump to the user defined task code. */\r
+       "                                                               \n"\r
+       "       .align 2                                        \n"\r
+       "pxCurrentTCBConst2: .word pxCurrentTCB   "                                     \r
                                  );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -281,7 +271,7 @@ void vClearInterruptMaskFromISR( unsigned long ulMask )
                                        " msr PRIMASK, r0       \n"\r
                                        " bx lr                           "\r
                                  );\r
-                                 \r
+\r
        /* Just to avoid compiler warning. */\r
        ( void ) ulMask;\r
 }\r