2 * FreeRTOS Kernel V11.2.0
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
29 /* Scheduler includes. */
34 /*-----------------------------------------------------------
35 * Implementation of functions defined in portable.h for the H8S port.
36 *----------------------------------------------------------*/
39 /*-----------------------------------------------------------*/
41 /* When the task starts interrupts should be enabled. */
42 #define portINITIAL_CCR ( ( StackType_t ) 0x00 )
44 /* Hardware specific constants used to generate the RTOS tick from the TPU. */
45 #define portCLEAR_ON_TGRA_COMPARE_MATCH ( ( uint8_t ) 0x20 )
46 #define portCLOCK_DIV_64 ( ( uint8_t ) 0x03 )
47 #define portCLOCK_DIV ( ( uint32_t ) 64 )
48 #define portTGRA_INTERRUPT_ENABLE ( ( uint8_t ) 0x01 )
49 #define portTIMER_CHANNEL ( ( uint8_t ) 0x02 )
50 #define portMSTP13 ( ( uint16_t ) 0x2000 )
53 * Setup TPU channel one for the RTOS tick at the requested frequency.
55 static void prvSetupTimerInterrupt( void );
58 * The ISR used by portYIELD(). This is installed as a trap handler.
60 void vPortYield( void ) __attribute__( ( saveall, interrupt_handler ) );
62 /*-----------------------------------------------------------*/
65 * See header file for description.
67 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
68 TaskFunction_t pxCode,
73 /* This requires an even address. */
74 ulValue = ( uint32_t ) pxTopOfStack;
78 pxTopOfStack = pxTopOfStack - 1;
81 /* Place a few bytes of known values on the bottom of the stack.
82 * This is just useful for debugging. */
92 /* The initial stack mimics an interrupt stack. First there is the program
93 * counter (24 bits). */
94 ulValue = ( uint32_t ) pxCode;
97 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
100 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
103 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
105 /* Followed by the CCR. */
107 *pxTopOfStack = portINITIAL_CCR;
109 /* Next all the general purpose registers - with the parameters being passed
110 * in ER0. The parameter order must match that used by the compiler when the
111 * "saveall" function attribute is used. */
115 *pxTopOfStack = 0x66;
117 *pxTopOfStack = 0x66;
119 *pxTopOfStack = 0x66;
121 *pxTopOfStack = 0x66;
124 ulValue = ( uint32_t ) pvParameters;
127 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
130 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
133 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
136 *pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
140 *pxTopOfStack = 0x11;
142 *pxTopOfStack = 0x11;
144 *pxTopOfStack = 0x11;
146 *pxTopOfStack = 0x11;
150 *pxTopOfStack = 0x22;
152 *pxTopOfStack = 0x22;
154 *pxTopOfStack = 0x22;
156 *pxTopOfStack = 0x22;
160 *pxTopOfStack = 0x33;
162 *pxTopOfStack = 0x33;
164 *pxTopOfStack = 0x33;
166 *pxTopOfStack = 0x33;
170 *pxTopOfStack = 0x44;
172 *pxTopOfStack = 0x44;
174 *pxTopOfStack = 0x44;
176 *pxTopOfStack = 0x44;
180 *pxTopOfStack = 0x55;
182 *pxTopOfStack = 0x55;
184 *pxTopOfStack = 0x55;
186 *pxTopOfStack = 0x55;
190 /*-----------------------------------------------------------*/
192 BaseType_t xPortStartScheduler( void )
194 extern void * pxCurrentTCB;
196 /* Setup the hardware to generate the tick. */
197 prvSetupTimerInterrupt();
199 /* Restore the context of the first task that is going to run. This
200 * mirrors the function epilogue code generated by the compiler when the
201 * "saveall" function attribute is used. */
203 "MOV.L @_pxCurrentTCB, ER6 \n\t"
204 "MOV.L @ER6, ER7 \n\t"
205 "LDM.L @SP+, (ER4-ER5) \n\t"
206 "LDM.L @SP+, (ER0-ER3) \n\t"
207 "MOV.L @ER7+, ER6 \n\t"
211 ( void ) pxCurrentTCB;
213 /* Should not get here. */
216 /*-----------------------------------------------------------*/
218 void vPortEndScheduler( void )
220 /* It is unlikely that the h8 port will get stopped. */
222 /*-----------------------------------------------------------*/
225 * Manual context switch. This is a trap handler. The "saveall" function
226 * attribute is used so the context is saved by the compiler prologue. All
227 * we have to do is save the stack pointer.
229 void vPortYield( void )
231 portSAVE_STACK_POINTER();
232 vTaskSwitchContext();
233 portRESTORE_STACK_POINTER();
235 /*-----------------------------------------------------------*/
238 * The interrupt handler installed for the RTOS tick depends on whether the
239 * preemptive or cooperative scheduler is being used.
241 #if ( configUSE_PREEMPTION == 1 )
244 * The preemptive scheduler is used so the ISR calls vTaskSwitchContext().
245 * The function prologue saves the context so all we have to do is save
248 void vTickISR( void ) __attribute__( ( saveall, interrupt_handler ) );
249 void vTickISR( void )
251 portSAVE_STACK_POINTER();
253 if( xTaskIncrementTick() != pdFALSE )
255 vTaskSwitchContext();
258 /* Clear the interrupt. */
261 portRESTORE_STACK_POINTER();
264 #else /* if ( configUSE_PREEMPTION == 1 ) */
267 * The cooperative scheduler is being used so all we have to do is
268 * periodically increment the tick. This can just be a normal ISR and
269 * the "saveall" attribute is not required.
271 void vTickISR( void ) __attribute__( ( interrupt_handler ) );
272 void vTickISR( void )
274 xTaskIncrementTick();
276 /* Clear the interrupt. */
280 #endif /* if ( configUSE_PREEMPTION == 1 ) */
281 /*-----------------------------------------------------------*/
284 * Setup timer 1 compare match to generate a tick interrupt.
286 static void prvSetupTimerInterrupt( void )
288 const uint32_t ulCompareMatch = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / portCLOCK_DIV;
290 /* Turn the module on. */
291 MSTPCR &= ~portMSTP13;
293 /* Configure timer 1. */
294 TCR1 = portCLEAR_ON_TGRA_COMPARE_MATCH | portCLOCK_DIV_64;
296 /* Configure the compare match value for a tick of configTICK_RATE_HZ. */
297 TGR1A = ulCompareMatch;
299 /* Start the timer and enable the interrupt - we can do this here as
300 * interrupts are globally disabled when this function is called. */
301 TIER1 |= portTGRA_INTERRUPT_ENABLE;
302 TSTR |= portTIMER_CHANNEL;
304 /*-----------------------------------------------------------*/