]> begriffs open source - freertos/blob - portable/GCC/RL78/port.c
Update SMP branch readme for port migration (#999)
[freertos] / portable / GCC / RL78 / port.c
1 /*
2  * FreeRTOS SMP Kernel V202110.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /* Scheduler includes. */
29 #include "FreeRTOS.h"
30 #include "task.h"
31
32 /* The critical nesting value is initialised to a non zero value to ensure
33 interrupts don't accidentally become enabled before the scheduler is started. */
34 #define portINITIAL_CRITICAL_NESTING  ( ( uint16_t ) 10 )
35
36 /* Initial PSW value allocated to a newly created task.
37  *   11000110
38  *   ||||||||-------------- Fill byte
39  *   |||||||--------------- Carry Flag cleared
40  *   |||||----------------- In-service priority Flags set to low level
41  *   ||||------------------ Register bank Select 0 Flag cleared
42  *   |||------------------- Auxiliary Carry Flag cleared
43  *   ||-------------------- Register bank Select 1 Flag cleared
44  *   |--------------------- Zero Flag set
45  *   ---------------------- Global Interrupt Flag set (enabled)
46  */
47 #define portPSW           ( 0xc6UL )
48
49 /* Each task maintains a count of the critical section nesting depth.  Each time
50 a critical section is entered the count is incremented.  Each time a critical
51 section is exited the count is decremented - with interrupts only being
52 re-enabled if the count is zero.
53
54 usCriticalNesting will get set to zero when the scheduler starts, but must
55 not be initialised to zero as that could cause problems during the startup
56 sequence. */
57 volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
58
59 /*-----------------------------------------------------------*/
60
61 /*
62  * Sets up the periodic ISR used for the RTOS tick.
63  */
64 __attribute__((weak)) void vApplicationSetupTimerInterrupt( void );
65
66 /*
67  * Starts the scheduler by loading the context of the first task to run.
68  * (defined in portasm.S).
69  */
70 extern void vPortStartFirstTask( void );
71
72 /*-----------------------------------------------------------*/
73
74 /*
75  * Initialise the stack of a task to look exactly as if a call to
76  * portSAVE_CONTEXT had been called.
77  *
78  * See the header file portable.h.
79  */
80 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
81 {
82 uint32_t *pulLocal;
83
84         /* Stack type and pointers to the stack type are both 2 bytes. */
85
86         /* Parameters are passed in on the stack, and written using a 32bit value
87         hence a space is left for the second two bytes. */
88         pxTopOfStack--;
89
90         /* Write in the parameter value. */
91         pulLocal =  ( uint32_t * ) pxTopOfStack;
92         *pulLocal = ( StackType_t ) pvParameters;
93         pxTopOfStack--;
94
95         /* The return address, leaving space for the first two bytes of the
96         32-bit value. */
97         pxTopOfStack--;
98         pulLocal = ( uint32_t * ) pxTopOfStack;
99         *pulLocal = ( uint32_t ) 0;
100         pxTopOfStack--;
101
102         /* The start address / PSW value is also written in as a 32bit value,
103         so leave a space for the second two bytes. */
104         pxTopOfStack--;
105
106         /* Task function start address combined with the PSW. */
107         pulLocal = ( uint32_t * ) pxTopOfStack;
108         *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
109         pxTopOfStack--;
110
111         /* An initial value for the AX register. */
112         *pxTopOfStack = ( StackType_t ) 0x1111;
113         pxTopOfStack--;
114
115         /* An initial value for the HL register. */
116         *pxTopOfStack = ( StackType_t ) 0x2222;
117         pxTopOfStack--;
118
119         /* CS and ES registers. */
120         *pxTopOfStack = ( StackType_t ) 0x0F00;
121         pxTopOfStack--;
122
123         /* The remaining general purpose registers bank 0 (DE and BC) and the other
124         two register banks...register bank 3 is dedicated for use by interrupts so
125         is not saved as part of the task context. */
126         pxTopOfStack -= 10;
127
128         /* Finally the critical section nesting count is set to zero when the task
129         first starts. */
130         *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
131
132         /* Return a pointer to the top of the stack that has beene generated so it
133         can     be stored in the task control block for the task. */
134         return pxTopOfStack;
135 }
136 /*-----------------------------------------------------------*/
137
138 portBASE_TYPE xPortStartScheduler( void )
139 {
140         /* Setup the hardware to generate the tick.  Interrupts are disabled when
141         this function is called. */
142         vApplicationSetupTimerInterrupt();
143
144         /* Restore the context of the first task that is going to run. */
145         vPortStartFirstTask();
146
147         /* Execution should not reach here as the tasks are now running! */
148         return pdTRUE;
149 }
150 /*-----------------------------------------------------------*/
151
152 void vPortEndScheduler( void )
153 {
154         /* It is unlikely that the RL78 port will get stopped. */
155 }
156 /*-----------------------------------------------------------*/
157
158 __attribute__((weak)) void vApplicationSetupTimerInterrupt( void )
159 {
160 const uint16_t usClockHz = 15000UL; /* Internal clock. */
161 const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;
162
163         /* Use the internal 15K clock. */
164         OSMC = ( unsigned char ) 0x16;
165
166         #ifdef RTCEN
167         {
168                 /* Supply the interval timer clock. */
169                 RTCEN = ( unsigned char ) 1U;
170
171                 /* Disable INTIT interrupt. */
172                 ITMK = ( unsigned char ) 1;
173
174                 /* Disable ITMC operation. */
175                 ITMC = ( unsigned char ) 0x0000;
176
177                 /* Clear INIT interrupt. */
178                 ITIF = ( unsigned char ) 0;
179
180                 /* Set interval and enable interrupt operation. */
181                 ITMC = usCompareMatch | 0x8000U;
182
183                 /* Enable INTIT interrupt. */
184                 ITMK = ( unsigned char ) 0;
185         }
186         #endif
187
188         #ifdef TMKAEN
189         {
190                 /* Supply the interval timer clock. */
191                 TMKAEN = ( unsigned char ) 1U;
192
193                 /* Disable INTIT interrupt. */
194                 TMKAMK = ( unsigned char ) 1;
195
196                 /* Disable ITMC operation. */
197                 ITMC = ( unsigned char ) 0x0000;
198
199                 /* Clear INIT interrupt. */
200                 TMKAIF = ( unsigned char ) 0;
201
202                 /* Set interval and enable interrupt operation. */
203                 ITMC = usCompareMatch | 0x8000U;
204
205                 /* Enable INTIT interrupt. */
206                 TMKAMK = ( unsigned char ) 0;
207         }
208         #endif
209 }
210 /*-----------------------------------------------------------*/
211