2 FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 ***************************************************************************
\r
46 * Having a problem? Start by reading the FAQ "My application does *
\r
47 * not run, what could be wrong? *
\r
49 * http://www.FreeRTOS.org/FAQHelp.html *
\r
51 ***************************************************************************
\r
54 http://www.FreeRTOS.org - Documentation, training, latest information,
\r
55 license and contact details.
\r
57 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
58 including FreeRTOS+Trace - an indispensable productivity tool.
\r
60 Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
\r
61 the code with commercial support, indemnification, and middleware, under
\r
62 the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
\r
63 provide a safety engineered and independently SIL3 certified version under
\r
64 the SafeRTOS brand: http://www.SafeRTOS.com.
\r
67 #include "FreeRTOS.h"
\r
69 #include "mb91467d.h"
\r
71 /*-----------------------------------------------------------*/
\r
73 /* We require the address of the pxCurrentTCB variable, but don't want to know
\r
74 any details of its type. */
\r
75 typedef void tskTCB;
\r
76 extern volatile tskTCB * volatile pxCurrentTCB;
\r
78 /*-----------------------------------------------------------*/
\r
82 ORCCR #0x20 ;Switch to user stack
\r
83 ST RP,@-R15 ;Store RP
\r
84 STM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Store R7-R0
\r
85 STM1 (R14,R13,R12,R11,R10,R9,R8) ;Store R14-R8
\r
86 ST MDH, @-R15 ;Store MDH
\r
87 ST MDL, @-R15 ;Store MDL
\r
89 ANDCCR #0xDF ;Switch back to system stack
\r
90 LD @R15+,R0 ;Store PC to R0
\r
91 ORCCR #0x20 ;Switch to user stack
\r
92 ST R0,@-R15 ;Store PC to User stack
\r
94 ANDCCR #0xDF ;Switch back to system stack
\r
95 LD @R15+,R0 ;Store PS to R0
\r
96 ORCCR #0x20 ;Switch to user stack
\r
97 ST R0,@-R15 ;Store PS to User stack
\r
99 LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
\r
100 LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
\r
101 ST R15,@R0 ;Store USP to pxCurrentTCB->pxTopOfStack
\r
103 ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
\r
106 #macro RestoreContext
\r
107 LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
\r
108 LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
\r
109 ORCCR #0x20 ;Switch to user stack
\r
110 LD @R0, R15 ;Restore USP from pxCurrentTCB->pxTopOfStack
\r
112 LD @R15+,R0 ;Store PS to R0
\r
113 ANDCCR #0xDF ;Switch to system stack
\r
114 ST R0,@-R15 ;Store PS to system stack
\r
116 ORCCR #0x20 ;Switch to user stack
\r
117 LD @R15+,R0 ;Store PC to R0
\r
118 ANDCCR #0xDF ;Switch to system stack
\r
119 ST R0,@-R15 ;Store PC to system stack
\r
121 ORCCR #0x20 ;Switch back to retrieve the remaining context
\r
123 LD @R15+, MDL ;Restore MDL
\r
124 LD @R15+, MDH ;Restore MDH
\r
125 LDM1 (R14,R13,R12,R11,R10,R9,R8) ;Restore R14-R8
\r
126 LDM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Restore R7-R0
\r
127 LD @R15+, RP ;Restore RP
\r
129 ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
\r
133 /*-----------------------------------------------------------*/
\r
136 * Perform hardware setup to enable ticks from timer 1,
\r
138 static void prvSetupTimerInterrupt( void );
\r
139 /*-----------------------------------------------------------*/
\r
142 * Initialise the stack of a task to look exactly as if a call to
\r
143 * portSAVE_CONTEXT had been called.
\r
145 * See the header file portable.h.
\r
147 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
\r
149 /* Place a few bytes of known values on the bottom of the stack.
\r
150 This is just useful for debugging. */
\r
152 *pxTopOfStack = 0x11111111;
\r
154 *pxTopOfStack = 0x22222222;
\r
156 *pxTopOfStack = 0x33333333;
\r
159 /* This is a redundant push to the stack, it may be required if
\r
160 in some implementations of the compiler the parameter to the task
\r
161 is passed on to the stack rather than in R4 register. */
\r
162 *pxTopOfStack = (portSTACK_TYPE)(pvParameters);
\r
165 *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; /* RP */
\r
167 *pxTopOfStack = ( portSTACK_TYPE ) 0x00007777; /* R7 */
\r
169 *pxTopOfStack = ( portSTACK_TYPE ) 0x00006666; /* R6 */
\r
171 *pxTopOfStack = ( portSTACK_TYPE ) 0x00005555; /* R5 */
\r
174 /* In the current implementation of the compiler the first
\r
175 parameter to the task (or function) is passed via R4 parameter
\r
176 to the task, hence the pvParameters pointer is copied into the R4
\r
177 register. See compiler manual section 4.6.2 for more information. */
\r
178 *pxTopOfStack = ( portSTACK_TYPE ) (pvParameters); /* R4 */
\r
180 *pxTopOfStack = ( portSTACK_TYPE ) 0x00003333; /* R3 */
\r
182 *pxTopOfStack = ( portSTACK_TYPE ) 0x00002222; /* R2 */
\r
184 *pxTopOfStack = ( portSTACK_TYPE ) 0x00001111; /* R1 */
\r
186 *pxTopOfStack = ( portSTACK_TYPE ) 0x00000001; /* R0 */
\r
188 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000EEEE; /* R14 */
\r
190 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000DDDD; /* R13 */
\r
192 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000CCCC; /* R12 */
\r
194 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000BBBB; /* R11 */
\r
196 *pxTopOfStack = ( portSTACK_TYPE ) 0x0000AAAA; /* R10 */
\r
198 *pxTopOfStack = ( portSTACK_TYPE ) 0x00009999; /* R9 */
\r
200 *pxTopOfStack = ( portSTACK_TYPE ) 0x00008888; /* R8 */
\r
202 *pxTopOfStack = ( portSTACK_TYPE ) 0x11110000; /* MDH */
\r
204 *pxTopOfStack = ( portSTACK_TYPE ) 0x22220000; /* MDL */
\r
207 /* The start of the task code. */
\r
208 *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
\r
211 /* PS - User Mode, USP, ILM=31, Interrupts enabled */
\r
212 *pxTopOfStack = ( portSTACK_TYPE ) 0x001F0030; /* PS */
\r
214 return pxTopOfStack;
\r
216 /*-----------------------------------------------------------*/
\r
218 portBASE_TYPE xPortStartScheduler( void )
\r
220 /* Setup the hardware to generate the tick. */
\r
221 prvSetupTimerInterrupt();
\r
223 /* Restore the context of the first task that is going to run. */
\r
228 /* Simulate a function call end as generated by the compiler. We will now
\r
229 jump to the start of the task the context of which we have just restored. */
\r
232 /* Should not get here. */
\r
235 /*-----------------------------------------------------------*/
\r
237 void vPortEndScheduler( void )
\r
239 /* Not implemented - unlikely to ever be required as there is nothing to
\r
242 /*-----------------------------------------------------------*/
\r
244 static void prvSetupTimerInterrupt( void )
\r
246 /* The peripheral clock divided by 32 is used by the timer. */
\r
247 const unsigned short usReloadValue = ( unsigned short ) ( ( ( configPER_CLOCK_HZ / configTICK_RATE_HZ ) / 32UL ) - 1UL );
\r
249 /* Setup RLT0 to generate a tick interrupt. */
\r
251 TMCSR0_CNTE = 0; /* Count Disable */
\r
252 TMCSR0_CSL = 0x2; /* CLKP/32 */
\r
253 TMCSR0_MOD = 0; /* Software trigger */
\r
254 TMCSR0_RELD = 1; /* Reload */
\r
256 TMCSR0_UF = 0; /* Clear underflow flag */
\r
257 TMRLR0 = usReloadValue;
\r
258 TMCSR0_INTE = 1; /* Interrupt Enable */
\r
259 TMCSR0_CNTE = 1; /* Count Enable */
\r
260 TMCSR0_TRG = 1; /* Trigger */
\r
262 PORTEN = 0x3; /* Port Enable */
\r
264 /*-----------------------------------------------------------*/
\r
266 #if configUSE_PREEMPTION == 1
\r
269 * Tick ISR for preemptive scheduler. The tick count is incremented
\r
270 * after the context is saved. Then the context is switched if required,
\r
271 * and last the context of the task which is to be resumed is restored.
\r
276 .global _ReloadTimer0_IRQHandler
\r
277 _ReloadTimer0_IRQHandler:
\r
279 ANDCCR #0xEF ;Disable Interrupts
\r
280 SaveContext ;Save context
\r
281 ORCCR #0x10 ;Re-enable Interrupts
\r
285 AND R1,@R0 ;Clear RLT0 interrupt flag
\r
287 CALL32 _vTaskIncrementTick,R12 ;Increment Tick
\r
288 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
290 ANDCCR #0xEF ;Disable Interrupts
\r
291 RestoreContext ;Restore context
\r
292 ORCCR #0x10 ;Re-enable Interrupts
\r
301 * Tick ISR for the cooperative scheduler. All this does is increment the
\r
302 * tick count. We don't need to switch context, this can only be done by
\r
303 * manual calls to taskYIELD();
\r
305 __interrupt void ReloadTimer0_IRQHandler( void )
\r
307 /* Clear RLT0 interrupt flag */
\r
309 vTaskIncrementTick();
\r
315 * Manual context switch. We can use a __nosavereg attribute as the context
\r
316 * would be saved by PortSAVE_CONTEXT(). The context is switched and then
\r
317 * the context of the new task is restored saved.
\r
321 .global _vPortYieldDelayed
\r
322 _vPortYieldDelayed:
\r
324 ANDCCR #0xEF ;Disable Interrupts
\r
325 SaveContext ;Save context
\r
326 ORCCR #0x10 ;Re-enable Interrupts
\r
329 BANDL #0x0E, @R0 ;Clear Delayed interrupt flag
\r
331 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
333 ANDCCR #0xEF ;Disable Interrupts
\r
334 RestoreContext ;Restore context
\r
335 ORCCR #0x10 ;Re-enable Interrupts
\r
340 /*-----------------------------------------------------------*/
\r
343 * Manual context switch. We can use a __nosavereg attribute as the context
\r
344 * would be saved by PortSAVE_CONTEXT(). The context is switched and then
\r
345 * the context of the new task is restored saved.
\r
349 .global _vPortYield
\r
352 SaveContext ;Save context
\r
353 CALL32 _vTaskSwitchContext,R12 ;Switch context if required
\r
354 RestoreContext ;Restore context
\r
359 /*-----------------------------------------------------------*/
\r