2 FreeRTOS.org V4.3.1 - Copyright (C) 2003-2007 Richard Barry.
4 This file is part of the FreeRTOS.org distribution.
6 FreeRTOS.org is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 FreeRTOS.org is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with FreeRTOS.org; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 A special exception to the GPL can be applied should you wish to distribute
21 a combined work that includes FreeRTOS.org, without being obliged to provide
22 the source code for any proprietary components. See the licensing section
23 of http://www.FreeRTOS.org for full details of how and when the exception
26 ***************************************************************************
27 See http://www.FreeRTOS.org for documentation, latest information, license
28 and contact details. Please ensure to read the configuration and relevant
29 port sections of the online documentation.
31 Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
32 with commercial development and support options.
33 ***************************************************************************
37 /*-----------------------------------------------------------
38 * Implementation of functions defined in portable.h for the ARM7 port.
40 * Components that can be compiled to either ARM or THUMB mode are
41 * contained in this file. The ISR routines, which can only be compiled
42 * to ARM mode are contained in portISR.c.
43 *----------------------------------------------------------*/
48 + ulCriticalNesting is now saved as part of the task context, as is
49 therefore added to the initial task stack during pxPortInitialiseStack.
53 + Bug fix - The prescale value for the timer setup is now written to T0_PR
54 instead of T0_PC. This bug would have had no effect unless a prescale
55 value was actually used.
59 /* Standard includes. */
62 /* Scheduler includes. */
66 /* Constants required to setup the task context. */
67 #define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
68 #define portTHUMB_MODE_BIT ( ( portSTACK_TYPE ) 0x20 )
69 #define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 4 )
70 #define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 )
72 /* Constants required to setup the tick ISR. */
73 #define portENABLE_TIMER ( ( unsigned portCHAR ) 0x01 )
74 #define portPRESCALE_VALUE 0x00
75 #define portINTERRUPT_ON_MATCH ( ( unsigned portLONG ) 0x01 )
76 #define portRESET_COUNT_ON_MATCH ( ( unsigned portLONG ) 0x02 )
78 /*-----------------------------------------------------------*/
80 /* Setup the timer to generate the tick interrupts. */
81 static void prvSetupTimerInterrupt( void );
84 * The scheduler can only be started from ARM mode, so
85 * vPortISRStartFirstSTask() is defined in portISR.c.
87 extern void vPortISRStartFirstTask( void );
89 /*-----------------------------------------------------------*/
92 * Initialise the stack of a task to look exactly as if a call to
93 * portSAVE_CONTEXT had been called.
95 * See header file for description.
97 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
99 portSTACK_TYPE *pxOriginalTOS;
101 pxOriginalTOS = pxTopOfStack;
103 /* Setup the initial stack of the task. The stack is set exactly as
104 expected by the portRESTORE_CONTEXT() macro. */
106 /* First on the stack is the return address - which in this case is the
107 start of the task. The offset is added to make the return address appear
108 as it would within an IRQ ISR. */
109 *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;
112 *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa; /* R14 */
114 *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
116 *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */
118 *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111; /* R11 */
120 *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010; /* R10 */
122 *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909; /* R9 */
124 *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808; /* R8 */
126 *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707; /* R7 */
128 *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606; /* R6 */
130 *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505; /* R5 */
132 *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404; /* R4 */
134 *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303; /* R3 */
136 *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202; /* R2 */
138 *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101; /* R1 */
141 /* When the task starts is will expect to find the function parameter in
143 *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
146 /* The last thing onto the stack is the status register, which is set for
147 system mode, with interrupts enabled. */
148 *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR;
150 #ifdef THUMB_INTERWORK
152 /* We want the task to start in thumb mode. */
153 *pxTopOfStack |= portTHUMB_MODE_BIT;
159 /* Some optimisation levels use the stack differently to others. This
160 means the interrupt flags cannot always be stored on the stack and will
161 instead be stored in a variable, which is then saved as part of the
163 *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
167 /*-----------------------------------------------------------*/
169 portBASE_TYPE xPortStartScheduler( void )
171 /* Start the timer that generates the tick ISR. Interrupts are disabled
173 prvSetupTimerInterrupt();
175 /* Start the first task. */
176 vPortISRStartFirstTask();
178 /* Should not get here! */
181 /*-----------------------------------------------------------*/
183 void vPortEndScheduler( void )
185 /* It is unlikely that the ARM port will require this function as there
186 is nothing to return to. */
188 /*-----------------------------------------------------------*/
191 * Setup the timer 0 to generate the tick interrupts at the required frequency.
193 static void prvSetupTimerInterrupt( void )
195 unsigned portLONG ulCompareMatch;
197 SCB_PCONP |= SCB_PCONP_PCTIM0;
199 /* A 1ms tick does not require the use of the timer prescale. This is
200 defaulted to zero but can be used if necessary. */
201 T0_PR = portPRESCALE_VALUE;
203 /* Calculate the match value required for our wanted tick rate. */
204 ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
206 /* Protect against divide by zero. Using an if() statement still results
207 in a warning - hence the #if. */
208 #if portPRESCALE_VALUE != 0
210 ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
213 T0_MR0 = ulCompareMatch;
215 /* Generate tick with timer 0 compare match. */
216 T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
218 /* Setup the VIC for the timer. */
219 VIC_IntSelect &= ~VIC_IntSelect_Timer0;
220 VIC_IntEnable = VIC_IntEnable_Timer0;
222 /* The ISR installed depends on whether the preemptive or cooperative
223 scheduler is being used. */
224 #if configUSE_PREEMPTION == 1
226 extern void ( vPreemptiveTick )( void );
227 VIC_VectAddr0 = ( portLONG ) vPreemptiveTick;
231 extern void ( vNonPreemptiveTick )( void );
232 VIC_VectAddr0 = ( portLONG ) vNonPreemptiveTick;
236 VIC_VectCntl0 = VIC_VectCntl_ENABLE | VIC_Channel_Timer0;
238 /* Start the timer - interrupts are disabled when this function is called
239 so it is okay to do this here. */
240 T0_TCR = portENABLE_TIMER;
242 /*-----------------------------------------------------------*/