Imported upstream version 1.20
[fw/openalt] / FreeRTOS / portable / GCC / ARM7_LPC2000 / port.c
1 /*
2         FreeRTOS.org V4.3.1 - Copyright (C) 2003-2007 Richard Barry.
3
4         This file is part of the FreeRTOS.org distribution.
5
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.
10
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.
15
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
19
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
24         can be applied.
25
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.
30
31         Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
32         with commercial development and support options.
33         ***************************************************************************
34 */
35
36
37 /*-----------------------------------------------------------
38  * Implementation of functions defined in portable.h for the ARM7 port.
39  *
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  *----------------------------------------------------------*/
44
45 /*
46         Changes from V2.5.2
47                 
48         + ulCriticalNesting is now saved as part of the task context, as is 
49           therefore added to the initial task stack during pxPortInitialiseStack.
50
51         Changes from V3.2.2
52
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.
56 */
57
58
59 /* Standard includes. */
60 #include <stdlib.h>
61
62 /* Scheduler includes. */
63 #include "FreeRTOS.h"
64 #include "task.h"
65
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 )
71
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 )
77
78 /*-----------------------------------------------------------*/
79
80 /* Setup the timer to generate the tick interrupts. */
81 static void prvSetupTimerInterrupt( void );
82
83 /* 
84  * The scheduler can only be started from ARM mode, so 
85  * vPortISRStartFirstSTask() is defined in portISR.c. 
86  */
87 extern void vPortISRStartFirstTask( void );
88
89 /*-----------------------------------------------------------*/
90
91 /* 
92  * Initialise the stack of a task to look exactly as if a call to 
93  * portSAVE_CONTEXT had been called.
94  *
95  * See header file for description. 
96  */
97 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
98 {
99 portSTACK_TYPE *pxOriginalTOS;
100
101         pxOriginalTOS = pxTopOfStack;
102
103         /* Setup the initial stack of the task.  The stack is set exactly as 
104         expected by the portRESTORE_CONTEXT() macro. */
105
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;               
110         pxTopOfStack--;
111
112         *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa;  /* R14 */
113         pxTopOfStack--; 
114         *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
115         pxTopOfStack--;
116         *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212;  /* R12 */
117         pxTopOfStack--; 
118         *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;  /* R11 */
119         pxTopOfStack--; 
120         *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010;  /* R10 */
121         pxTopOfStack--; 
122         *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909;  /* R9 */
123         pxTopOfStack--; 
124         *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808;  /* R8 */
125         pxTopOfStack--; 
126         *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707;  /* R7 */
127         pxTopOfStack--; 
128         *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606;  /* R6 */
129         pxTopOfStack--; 
130         *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505;  /* R5 */
131         pxTopOfStack--; 
132         *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404;  /* R4 */
133         pxTopOfStack--; 
134         *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303;  /* R3 */
135         pxTopOfStack--; 
136         *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202;  /* R2 */
137         pxTopOfStack--; 
138         *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101;  /* R1 */
139         pxTopOfStack--; 
140
141         /* When the task starts is will expect to find the function parameter in
142         R0. */
143         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
144         pxTopOfStack--;
145
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;
149
150         #ifdef THUMB_INTERWORK
151         {
152                 /* We want the task to start in thumb mode. */
153                 *pxTopOfStack |= portTHUMB_MODE_BIT;
154         }
155         #endif
156
157         pxTopOfStack--;
158
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
162         tasks context. */
163         *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
164
165         return pxTopOfStack;
166 }
167 /*-----------------------------------------------------------*/
168
169 portBASE_TYPE xPortStartScheduler( void )
170 {
171         /* Start the timer that generates the tick ISR.  Interrupts are disabled
172         here already. */
173         prvSetupTimerInterrupt();
174
175         /* Start the first task. */
176         vPortISRStartFirstTask();       
177
178         /* Should not get here! */
179         return 0;
180 }
181 /*-----------------------------------------------------------*/
182
183 void vPortEndScheduler( void )
184 {
185         /* It is unlikely that the ARM port will require this function as there
186         is nothing to return to.  */
187 }
188 /*-----------------------------------------------------------*/
189
190 /*
191  * Setup the timer 0 to generate the tick interrupts at the required frequency.
192  */
193 static void prvSetupTimerInterrupt( void )
194 {
195 unsigned portLONG ulCompareMatch;
196
197   SCB_PCONP |= SCB_PCONP_PCTIM0;
198
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;
202
203         /* Calculate the match value required for our wanted tick rate. */
204         ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
205
206         /* Protect against divide by zero.  Using an if() statement still results
207         in a warning - hence the #if. */
208         #if portPRESCALE_VALUE != 0
209         {
210                 ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
211         }
212         #endif
213         T0_MR0 = ulCompareMatch;
214
215         /* Generate tick with timer 0 compare match. */
216         T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
217
218         /* Setup the VIC for the timer. */
219         VIC_IntSelect &= ~VIC_IntSelect_Timer0;
220         VIC_IntEnable = VIC_IntEnable_Timer0;
221         
222         /* The ISR installed depends on whether the preemptive or cooperative
223         scheduler is being used. */
224         #if configUSE_PREEMPTION == 1
225         {
226                 extern void ( vPreemptiveTick )( void );
227                 VIC_VectAddr0 = ( portLONG ) vPreemptiveTick;
228         }
229         #else
230         {
231                 extern void ( vNonPreemptiveTick )( void );
232                 VIC_VectAddr0 = ( portLONG ) vNonPreemptiveTick;
233         }
234         #endif
235
236         VIC_VectCntl0 = VIC_VectCntl_ENABLE | VIC_Channel_Timer0;
237
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;
241 }
242 /*-----------------------------------------------------------*/
243
244
245