1
|
/*
|
2
|
FreeRTOS.org V4.2.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
|
|
52
|
|
53
|
/* Standard includes. */
|
54
|
#include <stdlib.h>
|
55
|
|
56
|
/* Scheduler includes. */
|
57
|
#include "FreeRTOS.h"
|
58
|
#include "task.h"
|
59
|
|
60
|
/* Processor constants. */
|
61
|
#include "AT91SAM7.h"
|
62
|
#include "lib_AT91SAM7.h"
|
63
|
|
64
|
/* Constants required to setup the task context. */
|
65
|
#define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
66
|
#define portTHUMB_MODE_BIT ( ( portSTACK_TYPE ) 0x20 )
|
67
|
#define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 4 )
|
68
|
#define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 )
|
69
|
|
70
|
/* Constants required to setup the tick ISR. */
|
71
|
#define portENABLE_TIMER ( ( unsigned portCHAR ) 0x01 )
|
72
|
#define portPRESCALE_VALUE 0x00
|
73
|
#define portINTERRUPT_ON_MATCH ( ( unsigned portLONG ) 0x01 )
|
74
|
#define portRESET_COUNT_ON_MATCH ( ( unsigned portLONG ) 0x02 )
|
75
|
|
76
|
/* Constants required to setup the PIT. */
|
77
|
#define portPIT_CLOCK_DIVISOR ( ( unsigned portLONG ) 16 )
|
78
|
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_RATE_MS )
|
79
|
|
80
|
#define portINT_LEVEL_SENSITIVE 0
|
81
|
#define portPIT_ENABLE ( ( unsigned portSHORT ) 0x1 << 24 )
|
82
|
#define portPIT_INT_ENABLE ( ( unsigned portSHORT ) 0x1 << 25 )
|
83
|
/*-----------------------------------------------------------*/
|
84
|
|
85
|
/* Setup the timer to generate the tick interrupts. */
|
86
|
static void prvSetupTimerInterrupt (void);
|
87
|
|
88
|
/*
|
89
|
* The scheduler can only be started from ARM mode, so
|
90
|
* vPortISRStartFirstSTask() is defined in portISR.c.
|
91
|
*/
|
92
|
extern void vPortISRStartFirstTask (void);
|
93
|
|
94
|
/*-----------------------------------------------------------*/
|
95
|
|
96
|
/*
|
97
|
* Initialise the stack of a task to look exactly as if a call to
|
98
|
* portSAVE_CONTEXT had been called.
|
99
|
*
|
100
|
* See header file for description.
|
101
|
*/
|
102
|
portSTACK_TYPE *
|
103
|
pxPortInitialiseStack (portSTACK_TYPE * pxTopOfStack, pdTASK_CODE pxCode,
|
104
|
void *pvParameters)
|
105
|
{
|
106
|
portSTACK_TYPE *pxOriginalTOS;
|
107
|
|
108
|
pxOriginalTOS = pxTopOfStack;
|
109
|
|
110
|
/* Setup the initial stack of the task. The stack is set exactly as
|
111
|
expected by the portRESTORE_CONTEXT() macro. */
|
112
|
|
113
|
/* First on the stack is the return address - which in this case is the
|
114
|
start of the task. The offset is added to make the return address appear
|
115
|
as it would within an IRQ ISR. */
|
116
|
*pxTopOfStack = (portSTACK_TYPE) pxCode + portINSTRUCTION_SIZE;
|
117
|
pxTopOfStack--;
|
118
|
|
119
|
*pxTopOfStack = (portSTACK_TYPE) 0xaaaaaaaa; /* R14 */
|
120
|
pxTopOfStack--;
|
121
|
*pxTopOfStack = (portSTACK_TYPE) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
122
|
pxTopOfStack--;
|
123
|
*pxTopOfStack = (portSTACK_TYPE) 0x12121212; /* R12 */
|
124
|
pxTopOfStack--;
|
125
|
*pxTopOfStack = (portSTACK_TYPE) 0x11111111; /* R11 */
|
126
|
pxTopOfStack--;
|
127
|
*pxTopOfStack = (portSTACK_TYPE) 0x10101010; /* R10 */
|
128
|
pxTopOfStack--;
|
129
|
*pxTopOfStack = (portSTACK_TYPE) 0x09090909; /* R9 */
|
130
|
pxTopOfStack--;
|
131
|
*pxTopOfStack = (portSTACK_TYPE) 0x08080808; /* R8 */
|
132
|
pxTopOfStack--;
|
133
|
*pxTopOfStack = (portSTACK_TYPE) 0x07070707; /* R7 */
|
134
|
pxTopOfStack--;
|
135
|
*pxTopOfStack = (portSTACK_TYPE) 0x06060606; /* R6 */
|
136
|
pxTopOfStack--;
|
137
|
*pxTopOfStack = (portSTACK_TYPE) 0x05050505; /* R5 */
|
138
|
pxTopOfStack--;
|
139
|
*pxTopOfStack = (portSTACK_TYPE) 0x04040404; /* R4 */
|
140
|
pxTopOfStack--;
|
141
|
*pxTopOfStack = (portSTACK_TYPE) 0x03030303; /* R3 */
|
142
|
pxTopOfStack--;
|
143
|
*pxTopOfStack = (portSTACK_TYPE) 0x02020202; /* R2 */
|
144
|
pxTopOfStack--;
|
145
|
*pxTopOfStack = (portSTACK_TYPE) 0x01010101; /* R1 */
|
146
|
pxTopOfStack--;
|
147
|
|
148
|
/* When the task starts is will expect to find the function parameter in
|
149
|
R0. */
|
150
|
*pxTopOfStack = (portSTACK_TYPE) pvParameters; /* R0 */
|
151
|
pxTopOfStack--;
|
152
|
|
153
|
/* The last thing onto the stack is the status register, which is set for
|
154
|
system mode, with interrupts enabled. */
|
155
|
*pxTopOfStack = (portSTACK_TYPE) portINITIAL_SPSR;
|
156
|
|
157
|
#ifdef THUMB_INTERWORK
|
158
|
{
|
159
|
/* We want the task to start in thumb mode. */
|
160
|
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
161
|
}
|
162
|
#endif
|
163
|
|
164
|
pxTopOfStack--;
|
165
|
|
166
|
/* Some optimisation levels use the stack differently to others. This
|
167
|
means the interrupt flags cannot always be stored on the stack and will
|
168
|
instead be stored in a variable, which is then saved as part of the
|
169
|
tasks context. */
|
170
|
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
171
|
|
172
|
return pxTopOfStack;
|
173
|
}
|
174
|
|
175
|
/*-----------------------------------------------------------*/
|
176
|
|
177
|
portBASE_TYPE
|
178
|
xPortStartScheduler (void)
|
179
|
{
|
180
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
181
|
here already. */
|
182
|
prvSetupTimerInterrupt ();
|
183
|
|
184
|
/* Start the first task. */
|
185
|
vPortISRStartFirstTask ();
|
186
|
|
187
|
/* Should not get here! */
|
188
|
return 0;
|
189
|
}
|
190
|
|
191
|
/*-----------------------------------------------------------*/
|
192
|
|
193
|
void
|
194
|
vPortEndScheduler (void)
|
195
|
{
|
196
|
/* It is unlikely that the ARM port will require this function as there
|
197
|
is nothing to return to. */
|
198
|
}
|
199
|
|
200
|
/*-----------------------------------------------------------*/
|
201
|
|
202
|
/*
|
203
|
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
204
|
*/
|
205
|
static void
|
206
|
prvSetupTimerInterrupt (void)
|
207
|
{
|
208
|
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
209
|
|
210
|
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
211
|
on whether the preemptive or cooperative scheduler is being used. */
|
212
|
#if configUSE_PREEMPTION == 0
|
213
|
|
214
|
extern void (vNonPreemptiveTick) (void);
|
215
|
AT91F_AIC_ConfigureIt (AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST,
|
216
|
portINT_LEVEL_SENSITIVE,
|
217
|
(void (*)(void)) vNonPreemptiveTick);
|
218
|
|
219
|
#else
|
220
|
|
221
|
extern void (vPreemptiveTick) (void);
|
222
|
AT91F_AIC_ConfigureIt (AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST,
|
223
|
portINT_LEVEL_SENSITIVE,
|
224
|
(void (*)(void)) vPreemptiveTick);
|
225
|
|
226
|
#endif
|
227
|
|
228
|
/* Configure the PIT period. */
|
229
|
pxPIT->PITC_PIMR =
|
230
|
portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
|
231
|
|
232
|
/* Enable the interrupt. Global interrupts are disables at this point so
|
233
|
this is safe. */
|
234
|
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
|
235
|
}
|
236
|
|
237
|
/*-----------------------------------------------------------*/
|