]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/IAR/AtmelSAM9XE/port.c
Update license information text files for the CLI, TCP and UDP products to be correct...
[freertos] / FreeRTOS / Source / portable / IAR / AtmelSAM9XE / port.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /*-----------------------------------------------------------\r
30  * Implementation of functions defined in portable.h for the Atmel ARM7 port.\r
31  *----------------------------------------------------------*/\r
32 \r
33 \r
34 /* Standard includes. */\r
35 #include <stdlib.h>\r
36 \r
37 /* Scheduler includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 \r
41 /* Hardware includes. */\r
42 #include <board.h>\r
43 #include <pio/pio.h>\r
44 #include <pio/pio_it.h>\r
45 #include <pit/pit.h>\r
46 #include <aic/aic.h>\r
47 #include <tc/tc.h>\r
48 #include <utility/led.h>\r
49 #include <utility/trace.h>\r
50 \r
51 /*-----------------------------------------------------------*/\r
52 \r
53 /* Constants required to setup the initial stack. */\r
54 #define portINITIAL_SPSR                                ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */\r
55 #define portTHUMB_MODE_BIT                              ( ( StackType_t ) 0x20 )\r
56 #define portINSTRUCTION_SIZE                    ( ( StackType_t ) 4 )\r
57 \r
58 /* Constants required to setup the PIT. */\r
59 #define port1MHz_IN_Hz                                  ( 1000000ul )\r
60 #define port1SECOND_IN_uS                               ( 1000000.0 )\r
61 \r
62 /* Constants required to handle critical sections. */\r
63 #define portNO_CRITICAL_NESTING                 ( ( uint32_t ) 0 )\r
64 \r
65 \r
66 #define portINT_LEVEL_SENSITIVE  0\r
67 #define portPIT_ENABLE          ( ( uint16_t ) 0x1 << 24 )\r
68 #define portPIT_INT_ENABLE      ( ( uint16_t ) 0x1 << 25 )\r
69 /*-----------------------------------------------------------*/\r
70 \r
71 /* Setup the PIT to generate the tick interrupts. */\r
72 static void prvSetupTimerInterrupt( void );\r
73 \r
74 /* The PIT interrupt handler - the RTOS tick. */\r
75 static void vPortTickISR( void );\r
76 \r
77 /* ulCriticalNesting will get set to zero when the first task starts.  It\r
78 cannot be initialised to 0 as this will cause interrupts to be enabled\r
79 during the kernel initialisation process. */\r
80 uint32_t ulCriticalNesting = ( uint32_t ) 9999;\r
81 \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 /*\r
85  * Initialise the stack of a task to look exactly as if a call to\r
86  * portSAVE_CONTEXT had been called.\r
87  *\r
88  * See header file for description.\r
89  */\r
90 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
91 {\r
92 StackType_t *pxOriginalTOS;\r
93 \r
94         pxOriginalTOS = pxTopOfStack;\r
95 \r
96         /* To ensure asserts in tasks.c don't fail, although in this case the assert\r
97         is not really required. */\r
98         pxTopOfStack--;\r
99 \r
100         /* Setup the initial stack of the task.  The stack is set exactly as\r
101         expected by the portRESTORE_CONTEXT() macro. */\r
102 \r
103         /* First on the stack is the return address - which in this case is the\r
104         start of the task.  The offset is added to make the return address appear\r
105         as it would within an IRQ ISR. */\r
106         *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;          \r
107         pxTopOfStack--;\r
108 \r
109         *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa;     /* R14 */\r
110         pxTopOfStack--; \r
111         *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */\r
112         pxTopOfStack--;\r
113         *pxTopOfStack = ( StackType_t ) 0x12121212;     /* R12 */\r
114         pxTopOfStack--; \r
115         *pxTopOfStack = ( StackType_t ) 0x11111111;     /* R11 */\r
116         pxTopOfStack--; \r
117         *pxTopOfStack = ( StackType_t ) 0x10101010;     /* R10 */\r
118         pxTopOfStack--; \r
119         *pxTopOfStack = ( StackType_t ) 0x09090909;     /* R9 */\r
120         pxTopOfStack--; \r
121         *pxTopOfStack = ( StackType_t ) 0x08080808;     /* R8 */\r
122         pxTopOfStack--; \r
123         *pxTopOfStack = ( StackType_t ) 0x07070707;     /* R7 */\r
124         pxTopOfStack--; \r
125         *pxTopOfStack = ( StackType_t ) 0x06060606;     /* R6 */\r
126         pxTopOfStack--; \r
127         *pxTopOfStack = ( StackType_t ) 0x05050505;     /* R5 */\r
128         pxTopOfStack--; \r
129         *pxTopOfStack = ( StackType_t ) 0x04040404;     /* R4 */\r
130         pxTopOfStack--; \r
131         *pxTopOfStack = ( StackType_t ) 0x03030303;     /* R3 */\r
132         pxTopOfStack--; \r
133         *pxTopOfStack = ( StackType_t ) 0x02020202;     /* R2 */\r
134         pxTopOfStack--; \r
135         *pxTopOfStack = ( StackType_t ) 0x01010101;     /* R1 */\r
136         pxTopOfStack--; \r
137 \r
138         /* When the task starts is will expect to find the function parameter in\r
139         R0. */\r
140         *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */\r
141         pxTopOfStack--;\r
142 \r
143         /* The status register is set for system mode, with interrupts enabled. */\r
144         *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;\r
145         \r
146         #ifdef THUMB_INTERWORK\r
147         {\r
148                 /* We want the task to start in thumb mode. */\r
149                 *pxTopOfStack |= portTHUMB_MODE_BIT;\r
150         }\r
151         #endif\r
152         \r
153         pxTopOfStack--;\r
154 \r
155         /* Interrupt flags cannot always be stored on the stack and will\r
156         instead be stored in a variable, which is then saved as part of the\r
157         tasks context. */\r
158         *pxTopOfStack = portNO_CRITICAL_NESTING;\r
159 \r
160         return pxTopOfStack;    \r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r
164 BaseType_t xPortStartScheduler( void )\r
165 {\r
166 extern void vPortStartFirstTask( void );\r
167 \r
168         /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
169         here already. */\r
170         prvSetupTimerInterrupt();\r
171 \r
172         /* Start the first task. */\r
173         vPortStartFirstTask();  \r
174 \r
175         /* Should not get here! */\r
176         return 0;\r
177 }\r
178 /*-----------------------------------------------------------*/\r
179 \r
180 void vPortEndScheduler( void )\r
181 {\r
182         /* It is unlikely that the ARM port will require this function as there\r
183         is nothing to return to.  */\r
184 }\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 static __arm void vPortTickISR( void )\r
188 {\r
189 volatile uint32_t ulDummy;\r
190         \r
191         /* Increment the tick count - which may wake some tasks but as the\r
192         preemptive scheduler is not being used any woken task is not given\r
193         processor time no matter what its priority. */\r
194         if( xTaskIncrementTick() != pdFALSE )\r
195         {\r
196                 vTaskSwitchContext();\r
197         }\r
198                 \r
199         /* Clear the PIT interrupt. */\r
200         ulDummy = AT91C_BASE_PITC->PITC_PIVR;\r
201         \r
202         /* To remove compiler warning. */\r
203         ( void ) ulDummy;\r
204         \r
205         /* The AIC is cleared in the asm wrapper, outside of this function. */\r
206 }\r
207 /*-----------------------------------------------------------*/\r
208 \r
209 static void prvSetupTimerInterrupt( void )\r
210 {\r
211 const uint32_t ulPeriodIn_uS = ( 1.0 / ( double ) configTICK_RATE_HZ ) * port1SECOND_IN_uS;\r
212 \r
213         /* Setup the PIT for the required frequency. */\r
214         PIT_Init( ulPeriodIn_uS, BOARD_MCK / port1MHz_IN_Hz );\r
215         \r
216         /* Setup the PIT interrupt. */\r
217         AIC_DisableIT( AT91C_ID_SYS );\r
218         AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortTickISR );\r
219         AIC_EnableIT( AT91C_ID_SYS );\r
220         PIT_EnableIT();\r
221 }\r
222 /*-----------------------------------------------------------*/\r
223 \r
224 void vPortEnterCritical( void )\r
225 {\r
226         /* Disable interrupts first! */\r
227         __disable_irq();\r
228 \r
229         /* Now interrupts are disabled ulCriticalNesting can be accessed\r
230         directly.  Increment ulCriticalNesting to keep a count of how many times\r
231         portENTER_CRITICAL() has been called. */\r
232         ulCriticalNesting++;\r
233 }\r
234 /*-----------------------------------------------------------*/\r
235 \r
236 void vPortExitCritical( void )\r
237 {\r
238         if( ulCriticalNesting > portNO_CRITICAL_NESTING )\r
239         {\r
240                 /* Decrement the nesting count as we are leaving a critical section. */\r
241                 ulCriticalNesting--;\r
242 \r
243                 /* If the nesting level has reached zero then interrupts should be\r
244                 re-enabled. */\r
245                 if( ulCriticalNesting == portNO_CRITICAL_NESTING )\r
246                 {\r
247                         __enable_irq();\r
248                 }\r
249         }\r
250 }\r
251 /*-----------------------------------------------------------*/\r
252 \r
253 \r
254 \r
255 \r
256 \r
257 \r