2 * FreeRTOS Kernel V10.3.1
\r
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
27 /* Scheduler includes. */
\r
28 #include "FreeRTOS.h"
\r
31 /* The critical nesting value is initialised to a non zero value to ensure
\r
32 * interrupts don't accidentally become enabled before the scheduler is started. */
\r
33 #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
\r
35 /* Initial PSW value allocated to a newly created task.
\r
37 * ||||||||-------------- Fill byte
\r
38 * |||||||--------------- Carry Flag cleared
\r
39 * |||||----------------- In-service priority Flags set to low level
\r
40 * ||||------------------ Register bank Select 0 Flag cleared
\r
41 * |||------------------- Auxiliary Carry Flag cleared
\r
42 * ||-------------------- Register bank Select 1 Flag cleared
\r
43 * |--------------------- Zero Flag set
\r
44 * ---------------------- Global Interrupt Flag set (enabled)
\r
46 #define portPSW ( 0xc6UL )
\r
48 /* The address of the pxCurrentTCB variable, but don't know or need to know its
\r
51 extern volatile TCB_t * volatile pxCurrentTCB;
\r
53 /* Each task maintains a count of the critical section nesting depth. Each time
\r
54 * a critical section is entered the count is incremented. Each time a critical
\r
55 * section is exited the count is decremented - with interrupts only being
\r
56 * re-enabled if the count is zero.
\r
58 * usCriticalNesting will get set to zero when the scheduler starts, but must
\r
59 * not be initialised to zero as that could cause problems during the startup
\r
61 volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
\r
63 /*-----------------------------------------------------------*/
\r
66 * Sets up the periodic ISR used for the RTOS tick using the interval timer.
\r
67 * The application writer can define configSETUP_TICK_INTERRUPT() (in
\r
68 * FreeRTOSConfig.h) such that their own tick interrupt configuration is used
\r
69 * in place of prvSetupTimerInterrupt().
\r
71 static void prvSetupTimerInterrupt( void );
\r
72 #ifndef configSETUP_TICK_INTERRUPT
\r
74 /* The user has not provided their own tick interrupt configuration so use
\r
75 * the definition in this file (which uses the interval timer). */
\r
76 #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
\r
77 #endif /* configSETUP_TICK_INTERRUPT */
\r
80 * Defined in portasm.s87, this function starts the scheduler by loading the
\r
81 * context of the first task to run.
\r
83 extern void vPortStartFirstTask( void );
\r
86 * Used to catch tasks that attempt to return from their implementing function.
\r
88 static void prvTaskExitError( void );
\r
90 /*-----------------------------------------------------------*/
\r
93 * Initialise the stack of a task to look exactly as if a call to
\r
94 * portSAVE_CONTEXT had been called.
\r
96 * See the header file portable.h.
\r
98 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
\r
99 TaskFunction_t pxCode,
\r
100 void * pvParameters )
\r
102 uint32_t * pulLocal;
\r
104 /* With large code and large data sizeof( StackType_t ) == 2, and
\r
105 * sizeof( StackType_t * ) == 4. With small code and small data
\r
106 * sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */
\r
108 #if __DATA_MODEL__ == __DATA_MODEL_FAR__
\r
110 /* Parameters are passed in on the stack, and written using a 32-bit value
\r
111 * hence a space is left for the second two bytes. */
\r
114 /* Write in the parameter value. */
\r
115 pulLocal = ( uint32_t * ) pxTopOfStack;
\r
116 *pulLocal = ( uint32_t ) pvParameters;
\r
119 /* The return address, leaving space for the first two bytes of the
\r
120 * 32-bit value. See the comments above the prvTaskExitError() prototype
\r
121 * at the top of this file. */
\r
123 pulLocal = ( uint32_t * ) pxTopOfStack;
\r
124 *pulLocal = ( uint32_t ) prvTaskExitError;
\r
127 /* The start address / PSW value is also written in as a 32-bit value,
\r
128 * so leave a space for the second two bytes. */
\r
131 /* Task function start address combined with the PSW. */
\r
132 pulLocal = ( uint32_t * ) pxTopOfStack;
\r
133 *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
\r
136 /* An initial value for the AX register. */
\r
137 *pxTopOfStack = ( StackType_t ) 0x1111;
\r
140 #else /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */
\r
142 /* The return address, leaving space for the first two bytes of the
\r
143 * 32-bit value. See the comments above the prvTaskExitError() prototype
\r
144 * at the top of this file. */
\r
146 pulLocal = ( uint32_t * ) pxTopOfStack;
\r
147 *pulLocal = ( uint32_t ) prvTaskExitError;
\r
150 /* Task function. Again as it is written as a 32-bit value a space is
\r
151 * left on the stack for the second two bytes. */
\r
154 /* Task function start address combined with the PSW. */
\r
155 pulLocal = ( uint32_t * ) pxTopOfStack;
\r
156 *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
\r
159 /* The parameter is passed in AX. */
\r
160 *pxTopOfStack = ( StackType_t ) pvParameters;
\r
163 #endif /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */
\r
165 /* An initial value for the HL register. */
\r
166 *pxTopOfStack = ( StackType_t ) 0x2222;
\r
169 /* CS and ES registers. */
\r
170 *pxTopOfStack = ( StackType_t ) 0x0F00;
\r
173 /* The remaining general purpose registers DE and BC */
\r
174 *pxTopOfStack = ( StackType_t ) 0xDEDE;
\r
176 *pxTopOfStack = ( StackType_t ) 0xBCBC;
\r
179 /* Finally the critical section nesting count is set to zero when the task
\r
181 *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
\r
183 /* Return a pointer to the top of the stack that has been generated so it
\r
184 * can be stored in the task control block for the task. */
\r
185 return pxTopOfStack;
\r
187 /*-----------------------------------------------------------*/
\r
189 static void prvTaskExitError( void )
\r
191 /* A function that implements a task must not exit or attempt to return to
\r
192 * its caller as there is nothing to return to. If a task wants to exit it
\r
193 * should instead call vTaskDelete( NULL ).
\r
195 * Artificially force an assert() to be triggered if configASSERT() is
\r
196 * defined, then stop here so application writers can catch the error. */
\r
197 configASSERT( usCriticalNesting == ~0U );
\r
198 portDISABLE_INTERRUPTS();
\r
204 /*-----------------------------------------------------------*/
\r
206 BaseType_t xPortStartScheduler( void )
\r
208 /* Setup the hardware to generate the tick. Interrupts are disabled when
\r
209 * this function is called. */
\r
210 configSETUP_TICK_INTERRUPT();
\r
212 /* Restore the context of the first task that is going to run. */
\r
213 vPortStartFirstTask();
\r
215 /* Execution should not reach here as the tasks are now running!
\r
216 * prvSetupTimerInterrupt() is called here to prevent the compiler outputting
\r
217 * a warning about a statically declared function not being referenced in the
\r
218 * case that the application writer has provided their own tick interrupt
\r
219 * configuration routine (and defined configSETUP_TICK_INTERRUPT() such that
\r
220 * their own routine will be called in place of prvSetupTimerInterrupt()). */
\r
221 prvSetupTimerInterrupt();
\r
224 /*-----------------------------------------------------------*/
\r
226 void vPortEndScheduler( void )
\r
228 /* It is unlikely that the RL78 port will get stopped. */
\r
230 /*-----------------------------------------------------------*/
\r
232 static void prvSetupTimerInterrupt( void )
\r
234 const uint16_t usClockHz = 15000UL; /* Internal clock. */
\r
235 const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;
\r
237 /* Use the internal 15K clock. */
\r
238 OSMC = ( uint8_t ) 0x16;
\r
242 /* Supply the interval timer clock. */
\r
243 RTCEN = ( uint8_t ) 1U;
\r
245 /* Disable INTIT interrupt. */
\r
246 ITMK = ( uint8_t ) 1;
\r
248 /* Disable ITMC operation. */
\r
249 ITMC = ( uint8_t ) 0x0000;
\r
251 /* Clear INIT interrupt. */
\r
252 ITIF = ( uint8_t ) 0;
\r
254 /* Set interval and enable interrupt operation. */
\r
255 ITMC = usCompareMatch | 0x8000U;
\r
257 /* Enable INTIT interrupt. */
\r
258 ITMK = ( uint8_t ) 0;
\r
260 #endif /* ifdef RTCEN */
\r
264 /* Supply the interval timer clock. */
\r
265 TMKAEN = ( uint8_t ) 1U;
\r
267 /* Disable INTIT interrupt. */
\r
268 TMKAMK = ( uint8_t ) 1;
\r
270 /* Disable ITMC operation. */
\r
271 ITMC = ( uint8_t ) 0x0000;
\r
273 /* Clear INIT interrupt. */
\r
274 TMKAIF = ( uint8_t ) 0;
\r
276 /* Set interval and enable interrupt operation. */
\r
277 ITMC = usCompareMatch | 0x8000U;
\r
279 /* Enable INTIT interrupt. */
\r
280 TMKAMK = ( uint8_t ) 0;
\r
282 #endif /* ifdef TMKAEN */
\r
284 /*-----------------------------------------------------------*/
\r