]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/IAR/RL78/port.c
1576130322ab3d1224f258dbddcefb42f8788e4c
[freertos] / FreeRTOS / Source / portable / IAR / RL78 / port.c
1 /*\r
2     FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* Scheduler includes. */\r
71 #include "FreeRTOS.h"\r
72 #include "task.h"\r
73 \r
74 /* The critical nesting value is initialised to a non zero value to ensure\r
75 interrupts don't accidentally become enabled before the scheduler is started. */\r
76 #define portINITIAL_CRITICAL_NESTING  ( ( uint16_t ) 10 )\r
77 \r
78 /* Initial PSW value allocated to a newly created task.\r
79  *   1100011000000000\r
80  *   ||||||||-------------- Fill byte\r
81  *   |||||||--------------- Carry Flag cleared\r
82  *   |||||----------------- In-service priority Flags set to low level\r
83  *   ||||------------------ Register bank Select 0 Flag cleared\r
84  *   |||------------------- Auxiliary Carry Flag cleared\r
85  *   ||-------------------- Register bank Select 1 Flag cleared\r
86  *   |--------------------- Zero Flag set\r
87  *   ---------------------- Global Interrupt Flag set (enabled)\r
88  */\r
89 #define portPSW           ( 0xc6UL )\r
90 \r
91 /* The address of the pxCurrentTCB variable, but don't know or need to know its\r
92 type. */\r
93 typedef void TCB_t;\r
94 extern volatile TCB_t * volatile pxCurrentTCB;\r
95 \r
96 /* Each task maintains a count of the critical section nesting depth.  Each time\r
97 a critical section is entered the count is incremented.  Each time a critical\r
98 section is exited the count is decremented - with interrupts only being\r
99 re-enabled if the count is zero.\r
100 \r
101 usCriticalNesting will get set to zero when the scheduler starts, but must\r
102 not be initialised to zero as that could cause problems during the startup\r
103 sequence. */\r
104 volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;\r
105 \r
106 /*-----------------------------------------------------------*/\r
107 \r
108 /*\r
109  * Sets up the periodic ISR used for the RTOS tick using the interval timer.\r
110  * The application writer can define configSETUP_TICK_INTERRUPT() (in\r
111  * FreeRTOSConfig.h) such that their own tick interrupt configuration is used\r
112  * in place of prvSetupTimerInterrupt().\r
113  */\r
114 static void prvSetupTimerInterrupt( void );\r
115 #ifndef configSETUP_TICK_INTERRUPT\r
116         /* The user has not provided their own tick interrupt configuration so use\r
117     the definition in this file (which uses the interval timer). */\r
118         #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()\r
119 #endif /* configSETUP_TICK_INTERRUPT */\r
120 \r
121 /*\r
122  * Defined in portasm.s87, this function starts the scheduler by loading the\r
123  * context of the first task to run.\r
124  */\r
125 extern void vPortStartFirstTask( void );\r
126 \r
127 /*\r
128  * Used to catch tasks that attempt to return from their implementing function.\r
129  */\r
130 static void prvTaskExitError( void );\r
131 \r
132 /*-----------------------------------------------------------*/\r
133 \r
134 /*\r
135  * Initialise the stack of a task to look exactly as if a call to\r
136  * portSAVE_CONTEXT had been called.\r
137  *\r
138  * See the header file portable.h.\r
139  */\r
140 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
141 {\r
142 uint32_t *pulLocal;\r
143 \r
144         /* With large code and large data sizeof( StackType_t ) == 2, and\r
145         sizeof( StackType_t * ) == 4.  With small code and small data\r
146         sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */\r
147 \r
148         #if __DATA_MODEL__ == __DATA_MODEL_FAR__\r
149         {\r
150                 /* Parameters are passed in on the stack, and written using a 32-bit value\r
151                 hence a space is left for the second two bytes. */\r
152                 pxTopOfStack--;\r
153 \r
154                 /* Write in the parameter value. */\r
155                 pulLocal =  ( uint32_t * ) pxTopOfStack;\r
156                 *pulLocal = ( uint32_t ) pvParameters;\r
157                 pxTopOfStack--;\r
158 \r
159                 /* The return address, leaving space for the first two bytes of the\r
160                 32-bit value.  See the comments above the prvTaskExitError() prototype\r
161                 at the top of this file. */\r
162                 pxTopOfStack--;\r
163                 pulLocal = ( uint32_t * ) pxTopOfStack;\r
164                 *pulLocal = ( uint32_t ) prvTaskExitError;\r
165                 pxTopOfStack--;\r
166 \r
167                 /* The start address / PSW value is also written in as a 32-bit value,\r
168                 so leave a space for the second two bytes. */\r
169                 pxTopOfStack--;\r
170 \r
171                 /* Task function start address combined with the PSW. */\r
172                 pulLocal = ( uint32_t * ) pxTopOfStack;\r
173                 *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );\r
174                 pxTopOfStack--;\r
175 \r
176                 /* An initial value for the AX register. */\r
177                 *pxTopOfStack = ( StackType_t ) 0x1111;\r
178                 pxTopOfStack--;\r
179         }\r
180         #else\r
181         {\r
182                 /* The return address, leaving space for the first two bytes of the\r
183                 32-bit value.  See the comments above the prvTaskExitError() prototype\r
184                 at the top of this file. */\r
185                 pxTopOfStack--;\r
186                 pulLocal = ( uint32_t * ) pxTopOfStack;\r
187                 *pulLocal = ( uint32_t ) prvTaskExitError;\r
188                 pxTopOfStack--;\r
189 \r
190                 /* Task function.  Again as it is written as a 32-bit value a space is\r
191                 left on the stack for the second two bytes. */\r
192                 pxTopOfStack--;\r
193 \r
194                 /* Task function start address combined with the PSW. */\r
195                 pulLocal = ( uint32_t * ) pxTopOfStack;\r
196                 *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );\r
197                 pxTopOfStack--;\r
198 \r
199                 /* The parameter is passed in AX. */\r
200                 *pxTopOfStack = ( StackType_t ) pvParameters;\r
201                 pxTopOfStack--;\r
202         }\r
203         #endif\r
204 \r
205         /* An initial value for the HL register. */\r
206         *pxTopOfStack = ( StackType_t ) 0x2222;\r
207         pxTopOfStack--;\r
208 \r
209         /* CS and ES registers. */\r
210         *pxTopOfStack = ( StackType_t ) 0x0F00;\r
211         pxTopOfStack--;\r
212 \r
213         /* The remaining general purpose registers DE and BC */\r
214         *pxTopOfStack = ( StackType_t ) 0xDEDE;\r
215         pxTopOfStack--;\r
216         *pxTopOfStack = ( StackType_t ) 0xBCBC;\r
217         pxTopOfStack--;\r
218 \r
219         /* Finally the critical section nesting count is set to zero when the task\r
220         first starts. */\r
221         *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;\r
222 \r
223         /* Return a pointer to the top of the stack that has been generated so it\r
224         can     be stored in the task control block for the task. */\r
225         return pxTopOfStack;\r
226 }\r
227 /*-----------------------------------------------------------*/\r
228 \r
229 static void prvTaskExitError( void )\r
230 {\r
231         /* A function that implements a task must not exit or attempt to return to\r
232         its caller as there is nothing to return to.  If a task wants to exit it\r
233         should instead call vTaskDelete( NULL ).\r
234 \r
235         Artificially force an assert() to be triggered if configASSERT() is\r
236         defined, then stop here so application writers can catch the error. */\r
237         configASSERT( usCriticalNesting == ~0U );\r
238         portDISABLE_INTERRUPTS();\r
239         for( ;; );\r
240 }\r
241 /*-----------------------------------------------------------*/\r
242 \r
243 BaseType_t xPortStartScheduler( void )\r
244 {\r
245         /* Setup the hardware to generate the tick.  Interrupts are disabled when\r
246         this function is called. */\r
247         configSETUP_TICK_INTERRUPT();\r
248 \r
249         /* Restore the context of the first task that is going to run. */\r
250         vPortStartFirstTask();\r
251 \r
252         /* Execution should not reach here as the tasks are now running!\r
253         prvSetupTimerInterrupt() is called here to prevent the compiler outputting\r
254         a warning about a statically declared function not being referenced in the\r
255         case that the application writer has provided their own tick interrupt\r
256         configuration routine (and defined configSETUP_TICK_INTERRUPT() such that\r
257         their own routine will be called in place of prvSetupTimerInterrupt()). */\r
258         prvSetupTimerInterrupt();\r
259         return pdTRUE;\r
260 }\r
261 /*-----------------------------------------------------------*/\r
262 \r
263 void vPortEndScheduler( void )\r
264 {\r
265         /* It is unlikely that the RL78 port will get stopped. */\r
266 }\r
267 /*-----------------------------------------------------------*/\r
268 \r
269 static void prvSetupTimerInterrupt( void )\r
270 {\r
271 const uint16_t usClockHz = 15000UL; /* Internal clock. */\r
272 const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;\r
273 \r
274         /* Use the internal 15K clock. */\r
275         OSMC = ( uint8_t ) 0x16;\r
276 \r
277         #ifdef RTCEN\r
278         {\r
279                 /* Supply the interval timer clock. */\r
280                 RTCEN = ( uint8_t ) 1U;\r
281 \r
282                 /* Disable INTIT interrupt. */\r
283                 ITMK = ( uint8_t ) 1;\r
284 \r
285                 /* Disable ITMC operation. */\r
286                 ITMC = ( uint8_t ) 0x0000;\r
287 \r
288                 /* Clear INIT interrupt. */\r
289                 ITIF = ( uint8_t ) 0;\r
290 \r
291                 /* Set interval and enable interrupt operation. */\r
292                 ITMC = usCompareMatch | 0x8000U;\r
293 \r
294                 /* Enable INTIT interrupt. */\r
295                 ITMK = ( uint8_t ) 0;\r
296         }\r
297         #endif\r
298 \r
299         #ifdef TMKAEN\r
300         {\r
301                 /* Supply the interval timer clock. */\r
302                 TMKAEN = ( uint8_t ) 1U;\r
303 \r
304                 /* Disable INTIT interrupt. */\r
305                 TMKAMK = ( uint8_t ) 1;\r
306 \r
307                 /* Disable ITMC operation. */\r
308                 ITMC = ( uint8_t ) 0x0000;\r
309 \r
310                 /* Clear INIT interrupt. */\r
311                 TMKAIF = ( uint8_t ) 0;\r
312 \r
313                 /* Set interval and enable interrupt operation. */\r
314                 ITMC = usCompareMatch | 0x8000U;\r
315 \r
316                 /* Enable INTIT interrupt. */\r
317                 TMKAMK = ( uint8_t ) 0;\r
318         }\r
319         #endif\r
320 }\r
321 /*-----------------------------------------------------------*/\r
322 \r