From 5affb6f050403a8298534cd83e475c5df96d8a4b Mon Sep 17 00:00:00 2001 From: richardbarry Date: Thu, 23 Oct 2008 11:03:25 +0000 Subject: First ARM7 port that uses the RVDS compiler. git-svn-id: https://freertos.svn.sourceforge.net/svnroot/freertos/trunk@511 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/RVDS/ARM7_LPC21xx/port.c | 310 ++++++++++++++++++++++++ Source/portable/RVDS/ARM7_LPC21xx/portASM.s | 132 ++++++++++ Source/portable/RVDS/ARM7_LPC21xx/portmacro.h | 162 +++++++++++++ Source/portable/RVDS/ARM7_LPC21xx/portmacro.inc | 113 +++++++++ 4 files changed, 717 insertions(+) create mode 100644 Source/portable/RVDS/ARM7_LPC21xx/port.c create mode 100644 Source/portable/RVDS/ARM7_LPC21xx/portASM.s create mode 100644 Source/portable/RVDS/ARM7_LPC21xx/portmacro.h create mode 100644 Source/portable/RVDS/ARM7_LPC21xx/portmacro.inc (limited to 'Source/portable') diff --git a/Source/portable/RVDS/ARM7_LPC21xx/port.c b/Source/portable/RVDS/ARM7_LPC21xx/port.c new file mode 100644 index 00000000..cfaaf1f1 --- /dev/null +++ b/Source/portable/RVDS/ARM7_LPC21xx/port.c @@ -0,0 +1,310 @@ +/* + FreeRTOS.org V5.0.4 - Copyright (C) 2003-2008 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FreeRTOS.org 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 + along with FreeRTOS.org; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + A special exception to the GPL can be applied should you wish to distribute + a combined work that includes FreeRTOS.org, without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details of how and when the exception + can be applied. + + *************************************************************************** + *************************************************************************** + * * + * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * + * and even write all or part of your application on your behalf. * + * See http://www.OpenRTOS.com for details of the services we provide to * + * expedite your project. * + * * + *************************************************************************** + *************************************************************************** + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* Standard includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to setup the initial task context. */ +#define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ +#define portTHUMB_MODE_BIT ( ( portSTACK_TYPE ) 0x20 ) +#define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 4 ) +#define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 ) + +/* Constants required to setup the tick ISR. */ +#define portENABLE_TIMER ( ( unsigned portCHAR ) 0x01 ) +#define portPRESCALE_VALUE 0x00 +#define portINTERRUPT_ON_MATCH ( ( unsigned portLONG ) 0x01 ) +#define portRESET_COUNT_ON_MATCH ( ( unsigned portLONG ) 0x02 ) + +/* Constants required to setup the VIC for the tick ISR. */ +#define portTIMER_VIC_CHANNEL ( ( unsigned portLONG ) 0x0004 ) +#define portTIMER_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x0010 ) +#define portTIMER_VIC_ENABLE ( ( unsigned portLONG ) 0x0020 ) + +/* Constants required to handle interrupts. */ +#define portTIMER_MATCH_ISR_BIT ( ( unsigned portCHAR ) 0x01 ) +#define portCLEAR_VIC_INTERRUPT ( ( unsigned portLONG ) 0 ) + +/*-----------------------------------------------------------*/ + +/* The code generated by the Keil compiler does not maintain separate +stack and frame pointers. The portENTER_CRITICAL macro cannot therefore +use the stack as per other ports. Instead a variable is used to keep +track of the critical section nesting. This variable has to be stored +as part of the task context and must be initialised to a non zero value. */ + +#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) +volatile unsigned portLONG ulCriticalNesting = 9999UL; + +/*-----------------------------------------------------------*/ + +/* Setup the timer to generate the tick interrupts. */ +static void prvSetupTimerInterrupt( void ); + +/* + * The scheduler can only be started from ARM mode, so + * vPortStartFirstSTask() is defined in portISR.c. + */ +extern __asm void vPortStartFirstTask( void ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ +portSTACK_TYPE *pxOriginalTOS; + + /* Setup the initial stack of the task. The stack is set exactly as + expected by the portRESTORE_CONTEXT() macro. + + Remember where the top of the (simulated) stack is before we place + anything on it. */ + pxOriginalTOS = pxTopOfStack; + + /* First on the stack is the return address - which in this case is the + start of the task. The offset is added to make the return address appear + as it would within an IRQ ISR. */ + *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; + pxTopOfStack--; + + *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa; /* R14 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909; /* R9 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808; /* R8 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707; /* R7 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606; /* R6 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505; /* R5 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404; /* R4 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101; /* R1 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack--; + + /* The last thing onto the stack is the status register, which is set for + system mode, with interrupts enabled. */ + *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR; + + #ifdef KEIL_THUMB_INTERWORK + { + /* We want the task to start in thumb mode. */ + *pxTopOfStack |= portTHUMB_MODE_BIT; + } + #endif + + pxTopOfStack--; + + /* The code generated by the Keil compiler does not maintain separate + stack and frame pointers. The portENTER_CRITICAL macro cannot therefore + use the stack as per other ports. Instead a variable is used to keep + track of the critical section nesting. This variable has to be stored + as part of the task context and is initially set to zero. */ + *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Start the timer that generates the tick ISR. */ + prvSetupTimerInterrupt(); + + /* Start the first task. This is done from portISR.c as ARM mode must be + used. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the ARM port will require this function as there + is nothing to return to. If this is required - stop the tick ISR then + return back to main. */ +} +/*-----------------------------------------------------------*/ + +#if configUSE_PREEMPTION == 0 + + /* + * The cooperative scheduler requires a normal IRQ service routine to + * simply increment the system tick. + */ + void vNonPreemptiveTick( void ) __irq; + void vNonPreemptiveTick( void ) __irq + { + /* Increment the tick count - this may make a delaying task ready + to run - but a context switch is not performed. */ + vTaskIncrementTick(); + + T0IR = portTIMER_MATCH_ISR_BIT; /* Clear the timer event */ + VICVectAddr = portCLEAR_VIC_INTERRUPT; /* Acknowledge the Interrupt */ + } + + #else + + /* + ************************************************************************** + * The preemptive scheduler ISR is written in assembler and can be found + * in the portASM.s file. This will only get used if portUSE_PREEMPTION + * is set to 1 in portmacro.h + ************************************************************************** + */ + + void vPreemptiveTick( void ); + +#endif +/*-----------------------------------------------------------*/ + +static void prvSetupTimerInterrupt( void ) +{ +unsigned portLONG ulCompareMatch; + + /* A 1ms tick does not require the use of the timer prescale. This is + defaulted to zero but can be used if necessary. */ + T0PR = portPRESCALE_VALUE; + + /* Calculate the match value required for our wanted tick rate. */ + ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; + + /* Protect against divide by zero. Using an if() statement still results + in a warning - hence the #if. */ + #if portPRESCALE_VALUE != 0 + { + ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); + } + #endif + + T0MR0 = ulCompareMatch; + + /* Generate tick with timer 0 compare match. */ + T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH; + + /* Setup the VIC for the timer. */ + VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT ); + VICIntEnable |= portTIMER_VIC_CHANNEL_BIT; + + /* The ISR installed depends on whether the preemptive or cooperative + scheduler is being used. */ + #if configUSE_PREEMPTION == 1 + { + VICVectAddr0 = ( unsigned portLONG ) vPreemptiveTick; + } + #else + { + VICVectAddr0 = ( unsigned portLONG ) vNonPreemptiveTick; + } + #endif + + VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; + + /* Start the timer - interrupts are disabled when this function is called + so it is okay to do this here. */ + T0TCR = portENABLE_TIMER; +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + /* Disable interrupts as per portDISABLE_INTERRUPTS(); */ + __disable_irq(); + + /* Now interrupts are disabled ulCriticalNesting can be accessed + directly. Increment ulCriticalNesting to keep a count of how many times + portENTER_CRITICAL() has been called. */ + ulCriticalNesting++; +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + if( ulCriticalNesting > portNO_CRITICAL_NESTING ) + { + /* Decrement the nesting count as we are leaving a critical section. */ + ulCriticalNesting--; + + /* If the nesting level has reached zero then interrupts should be + re-enabled. */ + if( ulCriticalNesting == portNO_CRITICAL_NESTING ) + { + /* Enable interrupts as per portEXIT_CRITICAL(). */ + __enable_irq(); + } + } +} +/*-----------------------------------------------------------*/ + + diff --git a/Source/portable/RVDS/ARM7_LPC21xx/portASM.s b/Source/portable/RVDS/ARM7_LPC21xx/portASM.s new file mode 100644 index 00000000..57740324 --- /dev/null +++ b/Source/portable/RVDS/ARM7_LPC21xx/portASM.s @@ -0,0 +1,132 @@ +;/* +; FreeRTOS.org V5.0.4 - Copyright (C) 2003-2008 Richard Barry. +; +; This file is part of the FreeRTOS.org distribution. +; +; FreeRTOS.org is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; FreeRTOS.org 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 +; along with FreeRTOS.org; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; A special exception to the GPL can be applied should you wish to distribute +; a combined work that includes FreeRTOS.org, without being obliged to provide +; the source code for any proprietary components. See the licensing section +; of http://www.FreeRTOS.org for full details of how and when the exception +; can be applied. +; +; *************************************************************************** +; *************************************************************************** +; * * +; * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * +; * and even write all or part of your application on your behalf. * +; * See http://www.OpenRTOS.com for details of the services we provide to * +; * expedite your project. * +; * * +; *************************************************************************** +; *************************************************************************** +; +; Please ensure to read the configuration and relevant port sections of the +; online documentation. +; +; http://www.FreeRTOS.org - Documentation, latest information, license and +; contact details. +; +; http://www.SafeRTOS.com - A version that is certified for use in safety +; critical systems. +; +; http://www.OpenRTOS.com - Commercial support, development, porting, +; licensing and training services. +;*/ + + INCLUDE portmacro.inc + + IMPORT vTaskSwitchContext + IMPORT vTaskIncrementTick + + EXPORT vPortYieldProcessor + EXPORT vPortStartFirstTask + EXPORT vPreemptiveTick + + + +VICVECTADDR EQU 0xFFFFF030 +T0IR EQU 0xE0004000 +T0MATCHBIT EQU 0x00000001 + + + ARM + AREA PORT_ASM, CODE, READONLY + PRESERVE8 + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Starting the first task is done by just restoring the context +; setup by pxPortInitialiseStack +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +vPortStartFirstTask + portRESTORE_CONTEXT + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Interrupt service routine for the SWI interrupt. The vector table is +; configured in the startup.s file. +; +; vPortYieldProcessor() is used to manually force a context switch. The +; SWI interrupt is generated by a call to taskYIELD() or portYIELD(). +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +vPortYieldProcessor + + ; Within an IRQ ISR the link register has an offset from the true return + ; address, but an SWI ISR does not. Add the offset manually so the same + ; ISR return code can be used in both cases. + ADD LR, LR, #4 + + ; Perform the context switch. + portSAVE_CONTEXT ; Save current task context + LDR R0, =vTaskSwitchContext ; Get the address of the context switch function + MOV LR, PC ; Store the return address + BX R0 ; Call the contedxt switch function + portRESTORE_CONTEXT ; restore the context of the selected task + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Interrupt service routine for preemptive scheduler tick timer +; Only used if portUSE_PREEMPTION is set to 1 in portmacro.h +; +; Uses timer 0 of LPC21XX Family +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +vPreemptiveTick + portSAVE_CONTEXT ; Save the context of the current task. + + LDR R0, =vTaskIncrementTick ; Increment the tick count. + MOV LR, PC ; This may make a delayed task ready + BX R0 ; to run. + + LDR R0, =vTaskSwitchContext ; Find the highest priority task that + MOV LR, PC ; is ready to run. + BX R0 + + MOV R0, #T0MATCHBIT ; Clear the timer event + LDR R1, =T0IR + STR R0, [R1] + + LDR R0, =VICVECTADDR ; Acknowledge the interrupt + STR R0,[R0] + + portRESTORE_CONTEXT ; Restore the context of the highest + ; priority task that is ready to run. + END + diff --git a/Source/portable/RVDS/ARM7_LPC21xx/portmacro.h b/Source/portable/RVDS/ARM7_LPC21xx/portmacro.h new file mode 100644 index 00000000..daa33065 --- /dev/null +++ b/Source/portable/RVDS/ARM7_LPC21xx/portmacro.h @@ -0,0 +1,162 @@ +/* + FreeRTOS.org V5.0.4 - Copyright (C) 2003-2008 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FreeRTOS.org 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 + along with FreeRTOS.org; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + A special exception to the GPL can be applied should you wish to distribute + a combined work that includes FreeRTOS.org, without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details of how and when the exception + can be applied. + + *************************************************************************** + *************************************************************************** + * * + * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * + * and even write all or part of your application on your behalf. * + * See http://www.OpenRTOS.com for details of the services we provide to * + * expedite your project. * + * * + *************************************************************************** + *************************************************************************** + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE portLONG + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 4 +/*-----------------------------------------------------------*/ + +/* Task utilities. */ + +/*----------------------------------------------------------- + * ISR entry and exit macros. These are only required if a task switch + * is required from an ISR. + *----------------------------------------------------------*/ + +/* If a switch is required then we just need to call */ +/* vTaskSwitchContext() as the context has already been */ +/* saved. */ + +#define portEXIT_SWITCHING_ISR(SwitchRequired) \ +{ \ +extern void vTaskSwitchContext(void); \ + \ + if(SwitchRequired) \ + { \ + vTaskSwitchContext(); \ + } \ +} \ + +#define portYIELD() __asm{ SVC 0 } + + +/* Critical section management. */ + +/* + ****************************************************************** + * We don't need to worry about whether we're in ARM or + * THUMB mode with the Keil Real View compiler when enabling + * or disabling interrupts as the compiler's intrinsic functions + * take care of that for us. + ******************************************************************* + */ +#define portDISABLE_INTERRUPTS() __disable_irq() +#define portENABLE_INTERRUPTS() __enable_irq() + + +/*----------------------------------------------------------- + * Critical section control + * + * The code generated by the Keil compiler does not maintain separate + * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore + * use the stack as per other ports. Instead a variable is used to keep + * track of the critical section nesting. This necessitates the use of a + * function in place of the macro. + *----------------------------------------------------------*/ + +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portENTER_CRITICAL() vPortEnterCritical(); +#define portEXIT_CRITICAL() vPortExitCritical(); +/*-----------------------------------------------------------*/ + +/* Compiler specifics. */ +#define inline +#define register +#define portNOP() __asm{ NOP } +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/Source/portable/RVDS/ARM7_LPC21xx/portmacro.inc b/Source/portable/RVDS/ARM7_LPC21xx/portmacro.inc new file mode 100644 index 00000000..36378e89 --- /dev/null +++ b/Source/portable/RVDS/ARM7_LPC21xx/portmacro.inc @@ -0,0 +1,113 @@ +;/* +; FreeRTOS.org V5.0.4 - Copyright (C) 2003-2008 Richard Barry. +; +; This file is part of the FreeRTOS.org distribution. +; +; FreeRTOS.org is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; FreeRTOS.org 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 +; along with FreeRTOS.org; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; A special exception to the GPL can be applied should you wish to distribute +; a combined work that includes FreeRTOS.org, without being obliged to provide +; the source code for any proprietary components. See the licensing section +; of http://www.FreeRTOS.org for full details of how and when the exception +; can be applied. +; +; *************************************************************************** +; *************************************************************************** +; * * +; * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * +; * and even write all or part of your application on your behalf. * +; * See http://www.OpenRTOS.com for details of the services we provide to * +; * expedite your project. * +; * * +; *************************************************************************** +; *************************************************************************** +; +; Please ensure to read the configuration and relevant port sections of the +; online documentation. +; +; http://www.FreeRTOS.org - Documentation, latest information, license and +; contact details. +; +; http://www.SafeRTOS.com - A version that is certified for use in safety +; critical systems. +; +; http://www.OpenRTOS.com - Commercial support, development, porting, +; licensing and training services. +;*/ + + IMPORT ulCriticalNesting ; + IMPORT pxCurrentTCB ; + + + MACRO + portRESTORE_CONTEXT + + + LDR R0, =pxCurrentTCB ; Set the LR to the task stack. The location was... + LDR R0, [R0] ; ... stored in pxCurrentTCB + LDR LR, [R0] + + LDR R0, =ulCriticalNesting ; The critical nesting depth is the first item on... + LDMFD LR!, {R1} ; ...the stack. Load it into the ulCriticalNesting var. + STR R1, [R0] ; + + LDMFD LR!, {R0} ; Get the SPSR from the stack. + MSR SPSR_cxsf, R0 ; + + LDMFD LR, {R0-R14}^ ; Restore all system mode registers for the task. + NOP ; + + LDR LR, [LR, #+60] ; Restore the return address + + ; And return - correcting the offset in the LR to obtain ... + SUBS PC, LR, #4 ; ...the correct address. + + MEND + +; /**********************************************************************/ + + MACRO + portSAVE_CONTEXT + + + STMDB SP!, {R0} ; Store R0 first as we need to use it. + + STMDB SP,{SP}^ ; Set R0 to point to the task stack pointer. + NOP ; + SUB SP, SP, #4 ; + LDMIA SP!,{R0} ; + + STMDB R0!, {LR} ; Push the return address onto the stack. + MOV LR, R0 ; Now we have saved LR we can use it instead of R0. + LDMIA SP!, {R0} ; Pop R0 so we can save it onto the system mode stack. + + STMDB LR,{R0-LR}^ ; Push all the system mode registers onto the task stack. + NOP ; + SUB LR, LR, #60 ; + + MRS R0, SPSR ; Push the SPSR onto the task stack. + STMDB LR!, {R0} ; + + LDR R0, =ulCriticalNesting ; + LDR R0, [R0] ; + STMDB LR!, {R0} ; + + LDR R0, =pxCurrentTCB ; Store the new top of stack for the task. + LDR R1, [R0] ; + STR LR, [R1] ; + + MEND + + END -- cgit v1.2.3