2 FreeRTOS.org V4.7.1 - Copyright (C) 2003-2008 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org 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
11 FreeRTOS.org 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
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, 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
26 ***************************************************************************
\r
28 Please ensure to read the configuration and relevant port sections of the
\r
29 online documentation.
\r
31 +++ http://www.FreeRTOS.org +++
\r
32 Documentation, latest information, license and contact details.
\r
34 +++ http://www.SafeRTOS.com +++
\r
35 A version that is certified for use in safety critical systems.
\r
37 +++ http://www.OpenRTOS.com +++
\r
38 Commercial support, development, porting, licensing and training services.
\r
40 ***************************************************************************
\r
43 #include "FreeRTOS.h"
\r
45 #include "mb91467d.h"
\r
47 /*-----------------------------------------------------------*/
\r
49 /* We require the address of the pxCurrentTCB variable, but don't want to know
\r
50 any details of its type. */
\r
51 typedef void tskTCB;
\r
52 extern volatile tskTCB * volatile pxCurrentTCB;
\r
54 /*-----------------------------------------------------------*/
\r
58 ORCCR #0x20 ;Switch to user stack
\r
59 ST RP,@-R15 ;Store RP
\r
60 STM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Store R7-R0
\r
61 STM1 (R14,R13,R12,R11,R10,R9,R8) ;Store R14-R8
\r
62 ST MDH, @-R15 ;Store MDH
\r
63 ST MDL, @-R15 ;Store MDL
\r
65 ANDCCR #0xDF ;Switch back to system stack
\r
66 LD @R15+,R0 ;Store PC to R0
\r
67 ORCCR #0x20 ;Switch to user stack
\r
68 ST R0,@-R15 ;Store PC to User stack
\r
70 ANDCCR #0xDF ;Switch back to system stack
\r
71 LD @R15+,R0 ;Store PS to R0
\r
72 ORCCR #0x20 ;Switch to user stack
\r
73 ST R0,@-R15 ;Store PS to User stack
\r
75 LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
\r
76 LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
\r
77 ST R15,@R0 ;Store USP to pxCurrentTCB->pxTopOfStack
\r
79 ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
\r
82 #macro RestoreContext
\r
83 LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
\r
84 LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
\r
85 ORCCR #0x20 ;Switch to user stack
\r
86 LD @R0, R15 ;Restore USP from pxCurrentTCB->pxTopOfStack
\r
88 LD @R15+,R0 ;Store PS to R0
\r
89 ANDCCR #0xDF ;Switch to system stack
\r
90 ST R0,@-R15 ;Store PS to system stack
\r
92 ORCCR #0x20 ;Switch to user stack
\r
93 LD @R15+,R0 ;Store PC to R0
\r
94 ANDCCR #0xDF ;Switch to system stack
\r
95 ST R0,@-R15 ;Store PC to system stack
\r
97 ORCCR #0x20 ;Switch back to retrieve the remaining context
\r
99 LD @R15+, MDL ;Restore MDL
\r
100 LD @R15+, MDH ;Restore MDH
\r
101 LDM1 (R14,R13,R12,R11,R10,R9,R8) ;Restore R14-R8
\r
102 LDM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Restore R7-R0
\r
103 LD @R15+, RP ;Restore RP
\r
105 ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
\r
109 /*-----------------------------------------------------------*/
\r
112 * Perform hardware setup to enable ticks from timer 1,
\r
114 static void prvSetupTimerInterrupt( void );
\r
115 /*-----------------------------------------------------------*/
\r
118 * Initialise the stack of a task to look exactly as if a call to
\r
119 * portSAVE_CONTEXT had been called.
\r
121 * See the header file portable.h.
\r
123 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
\r
125 /* Place a few bytes of known values on the bottom of the stack.
\r
126 This is just useful for debugging. */
\r
128 *pxTopOfStack = 0x11111111;
\r
130 *pxTopOfStack = 0x22222222;
\r
132 *pxTopOfStack = 0x33333333;
\r
135 /* This is a redundant push to the stack, it may be required if
\r
136 in some implementations of the compiler the parameter to the task
\r
137 is passed on to the stack rather than in R4 register. */
\r
138 *pxTopOfStack = (portSTACK_TYPE)(pvParameters);
\r
141 *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; /* RP */
\r
143 *pxTopOfStack = ( portSTACK_TYPE ) 0x00007777; /* R7 */
\r
145 *pxTopOfStack = ( portSTACK_TYPE ) 0x00006666; /* R6 */
\r
147 *pxTopOfStack = ( portSTACK_TYPE ) 0x00005555; /* R5 */
\r
150 /* In the current implementation of the compiler the first
\r
151 parameter to the task (or function) is passed via R4 parameter
\r
152 to the task, hence the pvParameters pointer is copied into the R4
\r
153 register. See compiler manual section 4.6.2 for more information. */
\r
154 *pxTopOfStack = ( portSTACK_TYPE ) (pvParameters); /* R4 */
\r
156 *pxTopOfStack = ( portSTACK_TYPE ) 0x00003333; /* R3 */
\r
158 *pxTopOfStack = ( portSTACK_TYPE ) 0x00002222; /* R2 */
\r
160 *pxTopOfStack = ( portSTACK_TYPE ) 0x00001111; /* R1 */
\r
162 *pxTopOfStack = ( portSTACK_TYPE ) 0x00000001; /* R0 */
\r
164 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000EEEE; /* R14 */
\r
166 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000DDDD; /* R13 */
\r
168 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000CCCC; /* R12 */
\r
170 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000BBBB; /* R11 */
\r
172 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000AAAA; /* R10 */
\r
174 *pxTopOfStack = ( portSTACK_TYPE ) 0x00009999; /* R9 */
\r
176 *pxTopOfStack = ( portSTACK_TYPE ) 0x00008888; /* R8 */
\r
178 *pxTopOfStack = ( portSTACK_TYPE ) 0x11110000; /* MDH */
\r
180 *pxTopOfStack = ( portSTACK_TYPE ) 0x22220000; /* MDL */
\r
183 /* The start of the task code. */
\r
184 *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
\r
187 /* PS - User Mode, USP, ILM=31, Interrupts enabled */
\r
188 *pxTopOfStack = ( portSTACK_TYPE ) 0x001F0030; /* PS */
\r
190 return pxTopOfStack;
\r
192 /*-----------------------------------------------------------*/
\r
194 portBASE_TYPE xPortStartScheduler( void )
\r
196 /* Setup the hardware to generate the tick. */
\r
197 prvSetupTimerInterrupt();
\r
199 /* Restore the context of the first task that is going to run. */
\r
204 /* Simulate a function call end as generated by the compiler. We will now
\r
205 jump to the start of the task the context of which we have just restored. */
\r
208 /* Should not get here. */
\r
211 /*-----------------------------------------------------------*/
\r
213 void vPortEndScheduler( void )
\r
215 /* Not implemented - unlikely to ever be required as there is nothing to
\r
218 /*-----------------------------------------------------------*/
\r
220 static void prvSetupTimerInterrupt( void )
\r
222 /* The peripheral clock divided by 32 is used by the timer. */
\r
223 const unsigned portSHORT usReloadValue = ( unsigned portSHORT ) ( ( ( configPER_CLOCK_HZ / configTICK_RATE_HZ ) / 32UL ) - 1UL );
\r
225 /* Setup RLT0 to generate a tick interrupt. */
\r
227 TMCSR0_CNTE = 0; /* Count Disable */
\r
228 TMCSR0_CSL = 0x2; /* CLKP/32 */
\r
229 TMCSR0_MOD = 0; /* Software trigger */
\r
230 TMCSR0_RELD = 1; /* Reload */
\r
232 TMCSR0_UF = 0; /* Clear underflow flag */
\r
233 TMRLR0 = usReloadValue;
\r
234 TMCSR0_INTE = 1; /* Interrupt Enable */
\r
235 TMCSR0_CNTE = 1; /* Count Enable */
\r
236 TMCSR0_TRG = 1; /* Trigger */
\r
238 PORTEN = 0x3; /* Port Enable */
\r
240 /*-----------------------------------------------------------*/
\r
242 #if configUSE_PREEMPTION == 1
\r
245 * Tick ISR for preemptive scheduler. The tick count is incremented
\r
246 * after the context is saved. Then the context is switched if required,
\r
247 * and last the context of the task which is to be resumed is restored.
\r
252 .global _ReloadTimer0_IRQHandler
\r
253 _ReloadTimer0_IRQHandler:
\r
255 ANDCCR #0xEF ;Disable Interrupts
\r
256 SaveContext ;Save context
\r
257 ORCCR #0x10 ;Re-enable Interrupts
\r
261 AND R1,@R0 ;Clear RLT0 interrupt flag
\r
263 CALL32 _vTaskIncrementTick,R12 ;Increment Tick
\r
264 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
266 ANDCCR #0xEF ;Disable Interrupts
\r
267 RestoreContext ;Restore context
\r
268 ORCCR #0x10 ;Re-enable Interrupts
\r
277 * Tick ISR for the cooperative scheduler. All this does is increment the
\r
278 * tick count. We don't need to switch context, this can only be done by
\r
279 * manual calls to taskYIELD();
\r
281 __interrupt void ReloadTimer0_IRQHandler( void )
\r
283 /* Clear RLT0 interrupt flag */
\r
285 vTaskIncrementTick();
\r
291 * Manual context switch. We can use a __nosavereg attribute as the context
\r
292 * would be saved by PortSAVE_CONTEXT(). The context is switched and then
\r
293 * the context of the new task is restored saved.
\r
297 .global _vPortYieldDelayed
\r
298 _vPortYieldDelayed:
\r
300 ANDCCR #0xEF ;Disable Interrupts
\r
301 SaveContext ;Save context
\r
302 ORCCR #0x10 ;Re-enable Interrupts
\r
305 BANDL #0x0E, @R0 ;Clear Delayed interrupt flag
\r
307 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
309 ANDCCR #0xEF ;Disable Interrupts
\r
310 RestoreContext ;Restore context
\r
311 ORCCR #0x10 ;Re-enable Interrupts
\r
316 /*-----------------------------------------------------------*/
\r
319 * Manual context switch. We can use a __nosavereg attribute as the context
\r
320 * would be saved by PortSAVE_CONTEXT(). The context is switched and then
\r
321 * the context of the new task is restored saved.
\r
325 .global _vPortYield
\r
328 SaveContext ;Save context
\r
329 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
330 RestoreContext ;Restore context
\r
335 /*-----------------------------------------------------------*/
\r