]> git.sur5r.net Git - freertos/blob - Source/portable/GCC/ARM7_AT91SAM7S/port.c
First version under SVN is V4.0.1
[freertos] / Source / portable / GCC / ARM7_AT91SAM7S / port.c
1 /*\r
2         FreeRTOS V4.0.1 - copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS distribution.\r
5 \r
6         FreeRTOS is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 \r
34 /*-----------------------------------------------------------\r
35  * Implementation of functions defined in portable.h for the ARM7 port.\r
36  *\r
37  * Components that can be compiled to either ARM or THUMB mode are\r
38  * contained in this file.  The ISR routines, which can only be compiled\r
39  * to ARM mode are contained in portISR.c.\r
40  *----------------------------------------------------------*/\r
41 \r
42 /*\r
43         Changes from V2.5.2\r
44                 \r
45         + ulCriticalNesting is now saved as part of the task context, as is \r
46           therefore added to the initial task stack during pxPortInitialiseStack.\r
47 */\r
48 \r
49 \r
50 /* Standard includes. */\r
51 #include <stdlib.h>\r
52 \r
53 /* Scheduler includes. */\r
54 #include "FreeRTOS.h"\r
55 #include "task.h"\r
56 \r
57 /* Processor constants. */\r
58 #include "AT91SAM7X256.h"\r
59 \r
60 /* Constants required to setup the task context. */\r
61 #define portINITIAL_SPSR                                ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */\r
62 #define portTHUMB_MODE_BIT                              ( ( portSTACK_TYPE ) 0x20 )\r
63 #define portINSTRUCTION_SIZE                    ( ( portSTACK_TYPE ) 4 )\r
64 #define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 )\r
65 \r
66 /* Constants required to setup the tick ISR. */\r
67 #define portENABLE_TIMER                        ( ( unsigned portCHAR ) 0x01 )\r
68 #define portPRESCALE_VALUE                      0x00\r
69 #define portINTERRUPT_ON_MATCH          ( ( unsigned portLONG ) 0x01 )\r
70 #define portRESET_COUNT_ON_MATCH        ( ( unsigned portLONG ) 0x02 )\r
71 \r
72 /* Constants required to setup the PIT. */\r
73 #define portPIT_CLOCK_DIVISOR                   ( ( unsigned portLONG ) 16 )\r
74 #define portPIT_COUNTER_VALUE                   ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_RATE_MS )\r
75 \r
76 #define portINT_LEVEL_SENSITIVE  0\r
77 #define portPIT_ENABLE          ( ( unsigned portSHORT ) 0x1 << 24 )\r
78 #define portPIT_INT_ENABLE      ( ( unsigned portSHORT ) 0x1 << 25 )\r
79 /*-----------------------------------------------------------*/\r
80 \r
81 /* Setup the timer to generate the tick interrupts. */\r
82 static void prvSetupTimerInterrupt( void );\r
83 \r
84 /* \r
85  * The scheduler can only be started from ARM mode, so \r
86  * vPortISRStartFirstSTask() is defined in portISR.c. \r
87  */\r
88 extern void vPortISRStartFirstTask( void );\r
89 \r
90 /*-----------------------------------------------------------*/\r
91 \r
92 /* \r
93  * Initialise the stack of a task to look exactly as if a call to \r
94  * portSAVE_CONTEXT had been called.\r
95  *\r
96  * See header file for description. \r
97  */\r
98 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
99 {\r
100 portSTACK_TYPE *pxOriginalTOS;\r
101 \r
102         pxOriginalTOS = pxTopOfStack;\r
103 \r
104         /* Setup the initial stack of the task.  The stack is set exactly as \r
105         expected by the portRESTORE_CONTEXT() macro. */\r
106 \r
107         /* First on the stack is the return address - which in this case is the\r
108         start of the task.  The offset is added to make the return address appear\r
109         as it would within an IRQ ISR. */\r
110         *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;               \r
111         pxTopOfStack--;\r
112 \r
113         *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa;  /* R14 */\r
114         pxTopOfStack--; \r
115         *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */\r
116         pxTopOfStack--;\r
117         *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212;  /* R12 */\r
118         pxTopOfStack--; \r
119         *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;  /* R11 */\r
120         pxTopOfStack--; \r
121         *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010;  /* R10 */\r
122         pxTopOfStack--; \r
123         *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909;  /* R9 */\r
124         pxTopOfStack--; \r
125         *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808;  /* R8 */\r
126         pxTopOfStack--; \r
127         *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707;  /* R7 */\r
128         pxTopOfStack--; \r
129         *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606;  /* R6 */\r
130         pxTopOfStack--; \r
131         *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505;  /* R5 */\r
132         pxTopOfStack--; \r
133         *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404;  /* R4 */\r
134         pxTopOfStack--; \r
135         *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303;  /* R3 */\r
136         pxTopOfStack--; \r
137         *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202;  /* R2 */\r
138         pxTopOfStack--; \r
139         *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101;  /* R1 */\r
140         pxTopOfStack--; \r
141 \r
142         /* When the task starts is will expect to find the function parameter in\r
143         R0. */\r
144         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */\r
145         pxTopOfStack--;\r
146 \r
147         /* The last thing onto the stack is the status register, which is set for\r
148         system mode, with interrupts enabled. */\r
149         *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR;\r
150 \r
151         #ifdef THUMB_INTERWORK\r
152         {\r
153                 /* We want the task to start in thumb mode. */\r
154                 *pxTopOfStack |= portTHUMB_MODE_BIT;\r
155         }\r
156         #endif\r
157 \r
158         pxTopOfStack--;\r
159 \r
160         /* Some optimisation levels use the stack differently to others.  This \r
161         means the interrupt flags cannot always be stored on the stack and will\r
162         instead be stored in a variable, which is then saved as part of the\r
163         tasks context. */\r
164         *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;\r
165 \r
166         return pxTopOfStack;\r
167 }\r
168 /*-----------------------------------------------------------*/\r
169 \r
170 portBASE_TYPE xPortStartScheduler( void )\r
171 {\r
172         /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
173         here already. */\r
174         prvSetupTimerInterrupt();\r
175 \r
176         /* Start the first task. */\r
177         vPortISRStartFirstTask();       \r
178 \r
179         /* Should not get here! */\r
180         return 0;\r
181 }\r
182 /*-----------------------------------------------------------*/\r
183 \r
184 void vPortEndScheduler( void )\r
185 {\r
186         /* It is unlikely that the ARM port will require this function as there\r
187         is nothing to return to.  */\r
188 }\r
189 /*-----------------------------------------------------------*/\r
190 \r
191 /*\r
192  * Setup the timer 0 to generate the tick interrupts at the required frequency.\r
193  */\r
194 static void prvSetupTimerInterrupt( void )\r
195 {\r
196 AT91PS_PITC pxPIT = AT91C_BASE_PITC;\r
197 \r
198         /* Setup the AIC for PIT interrupts.  The interrupt routine chosen depends\r
199         on whether the preemptive or cooperative scheduler is being used. */\r
200         #if configUSE_PREEMPTION == 0\r
201 \r
202                 extern void ( vNonPreemptiveTick ) ( void );\r
203                 AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );\r
204 \r
205         #else\r
206                 \r
207                 extern void ( vPreemptiveTick )( void );\r
208                 AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );\r
209 \r
210         #endif\r
211 \r
212         /* Configure the PIT period. */\r
213         pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;\r
214 \r
215         /* Enable the interrupt.  Global interrupts are disables at this point so \r
216         this is safe. */\r
217     AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;\r
218 }\r
219 /*-----------------------------------------------------------*/\r
220 \r
221 \r
222 \r