]> begriffs open source - cmsis-freertos/blob - Source/portable/WizC/PIC18/port.c
Updated pack to FreeRTOS 10.4.4
[cmsis-freertos] / Source / portable / WizC / PIC18 / port.c
1 /*
2  * FreeRTOS Kernel V10.4.4
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
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.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /*
30 Changes from V3.2.1
31         + CallReturn Depth increased from 8 to 10 levels to accomodate wizC/fedC V12.
32
33 Changes from V3.2.0
34         + TBLPTRU is now initialised to zero during the initial stack creation of a new task. This solves
35         an error on devices with more than 64kB ROM.
36
37 Changes from V3.0.0
38         + ucCriticalNesting is now initialised to 0x7F to prevent interrupts from being
39           handled before the scheduler is started.
40
41 Changes from V3.0.1
42 */
43
44 /* Scheduler include files. */
45 #include <FreeRTOS.h>
46 #include <task.h>
47
48 #include <malloc.h>
49
50 /*---------------------------------------------------------------------------
51  * Implementation of functions defined in portable.h for the WizC PIC18 port.
52  *---------------------------------------------------------------------------*/
53
54 /*
55  * We require the address of the pxCurrentTCB variable, but don't want to
56  * know any details of its type.
57  */
58 typedef void TCB_t;
59 extern volatile TCB_t * volatile pxCurrentTCB;
60
61 /*
62  * Define minimal-stack constants
63  * -----
64  * FSR's:
65  *              STATUS, WREG, BSR, PRODH, PRODL, FSR0H, FSR0L,
66  *              FSR1H, FSR1L,TABLAT, (TBLPTRU), TBLPTRH, TBLPTRL,
67  *              (PCLATU), PCLATH
68  *              sfr's within parenthesis only on devices > 64kB
69  * -----
70  * Call/Return stack:
71  *               2 bytes per entry on devices <= 64kB
72  *               3 bytes per entry on devices >  64kB
73  * -----
74  * Other bytes:
75  *               2 bytes: FunctionParameter for initial taskcode
76  *               1 byte : Number of entries on call/return stack
77  *               1 byte : ucCriticalNesting
78  *              16 bytes: Free space on stack
79  */
80 #if _ROMSIZE > 0x8000
81         #define portSTACK_FSR_BYTES                             ( 15 )
82         #define portSTACK_CALLRETURN_ENTRY_SIZE (  3 )
83 #else
84         #define portSTACK_FSR_BYTES                             ( 13 )
85         #define portSTACK_CALLRETURN_ENTRY_SIZE (  2 )
86 #endif
87
88 #define portSTACK_MINIMAL_CALLRETURN_DEPTH      ( 10 )
89 #define portSTACK_OTHER_BYTES                           ( 20 )
90
91 uint16_t usCalcMinStackSize             = 0;
92
93 /*-----------------------------------------------------------*/
94
95 /*
96  * We initialise ucCriticalNesting to the middle value an
97  * uint8_t can contain. This way portENTER_CRITICAL()
98  * and portEXIT_CRITICAL() can be called without interrupts
99  * being enabled before the scheduler starts.
100  */
101 register uint8_t ucCriticalNesting = 0x7F;
102
103 /*-----------------------------------------------------------*/
104
105 /*
106  * Initialise the stack of a new task.
107  * See portSAVE_CONTEXT macro for description.
108  */
109 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
110 {
111 uint8_t ucScratch;
112         /*
113          * Get the size of the RAMarea in page 0 used by the compiler
114          * We do this here already to avoid W-register conflicts.
115          */
116         _Pragma("asm")
117                 movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE
118                 movwf   PRODL,ACCESS            ; PRODL is used as temp register
119         _Pragma("asmend")
120         ucScratch = PRODL;
121
122         /*
123          * Place a few bytes of known values on the bottom of the stack.
124          * This is just useful for debugging.
125          */
126 //      *pxTopOfStack-- = 0x11;
127 //      *pxTopOfStack-- = 0x22;
128 //      *pxTopOfStack-- = 0x33;
129
130         /*
131          * Simulate how the stack would look after a call to vPortYield()
132          * generated by the compiler.
133          */
134
135         /*
136          * First store the function parameters.  This is where the task expects
137          * to find them when it starts running.
138          */
139         *pxTopOfStack-- = ( StackType_t ) ( (( uint16_t ) pvParameters >> 8) & 0x00ff );
140         *pxTopOfStack-- = ( StackType_t ) (  ( uint16_t ) pvParameters       & 0x00ff );
141
142         /*
143          * Next are all the registers that form part of the task context.
144          */
145         *pxTopOfStack-- = ( StackType_t ) 0x11; /* STATUS. */
146         *pxTopOfStack-- = ( StackType_t ) 0x22; /* WREG. */
147         *pxTopOfStack-- = ( StackType_t ) 0x33; /* BSR. */
148         *pxTopOfStack-- = ( StackType_t ) 0x44; /* PRODH. */
149         *pxTopOfStack-- = ( StackType_t ) 0x55; /* PRODL. */
150         *pxTopOfStack-- = ( StackType_t ) 0x66; /* FSR0H. */
151         *pxTopOfStack-- = ( StackType_t ) 0x77; /* FSR0L. */
152         *pxTopOfStack-- = ( StackType_t ) 0x88; /* FSR1H. */
153         *pxTopOfStack-- = ( StackType_t ) 0x99; /* FSR1L. */
154         *pxTopOfStack-- = ( StackType_t ) 0xAA; /* TABLAT. */
155 #if _ROMSIZE > 0x8000
156         *pxTopOfStack-- = ( StackType_t ) 0x00; /* TBLPTRU. */
157 #endif
158         *pxTopOfStack-- = ( StackType_t ) 0xCC; /* TBLPTRH. */
159         *pxTopOfStack-- = ( StackType_t ) 0xDD; /* TBLPTRL. */
160 #if _ROMSIZE > 0x8000
161         *pxTopOfStack-- = ( StackType_t ) 0xEE; /* PCLATU. */
162 #endif
163         *pxTopOfStack-- = ( StackType_t ) 0xFF; /* PCLATH. */
164
165         /*
166          * Next the compiler's scratchspace.
167          */
168         while(ucScratch-- > 0)
169         {
170                 *pxTopOfStack-- = ( StackType_t ) 0;
171         }
172
173         /*
174          * The only function return address so far is the address of the task entry.
175          * The order is TOSU/TOSH/TOSL. For devices > 64kB, TOSU is put on the
176          * stack, too. TOSU is always written as zero here because wizC does not allow
177          * functionpointers to point above 64kB in ROM.
178          */
179 #if _ROMSIZE > 0x8000
180         *pxTopOfStack-- = ( StackType_t ) 0;
181 #endif
182         *pxTopOfStack-- = ( StackType_t ) ( ( ( uint16_t ) pxCode >> 8 ) & 0x00ff );
183         *pxTopOfStack-- = ( StackType_t ) ( (   uint16_t ) pxCode        & 0x00ff );
184
185         /*
186          * Store the number of return addresses on the hardware stack.
187          * So far only the address of the task entry point.
188          */
189         *pxTopOfStack-- = ( StackType_t ) 1;
190
191         /*
192          * The code generated by wizC does not maintain separate
193          * stack and frame pointers. Therefore the portENTER_CRITICAL macro cannot
194          * use the stack as per other ports.  Instead a variable is used to keep
195          * track of the critical section nesting.  This variable has to be stored
196          * as part of the task context and is initially set to zero.
197          */
198         *pxTopOfStack-- = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
199
200         return pxTopOfStack;
201 }
202 /*-----------------------------------------------------------*/
203
204 uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void )
205 {
206         /*
207          * Fetch the size of compiler's scratchspace.
208          */
209         _Pragma("asm")
210                 movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE
211                 movlb   usCalcMinStackSize>>8
212                 movwf   usCalcMinStackSize,BANKED
213         _Pragma("asmend")
214
215         /*
216          * Add minimum needed stackspace
217          */
218         usCalcMinStackSize      +=      ( portSTACK_FSR_BYTES )
219                 +       ( portSTACK_MINIMAL_CALLRETURN_DEPTH * portSTACK_CALLRETURN_ENTRY_SIZE )
220                 +       ( portSTACK_OTHER_BYTES );
221
222         return(usCalcMinStackSize);
223 }
224
225 /*-----------------------------------------------------------*/
226
227 BaseType_t xPortStartScheduler( void )
228 {
229         extern void portSetupTick( void );
230
231         /*
232          * Setup a timer for the tick ISR for the preemptive scheduler.
233          */
234         portSetupTick();
235
236         /*
237          * Restore the context of the first task to run.
238          */
239         portRESTORE_CONTEXT();
240
241         /*
242          * This point should never be reached during execution.
243          */
244         return pdTRUE;
245 }
246
247 /*-----------------------------------------------------------*/
248
249 void vPortEndScheduler( void )
250 {
251         /*
252          * It is unlikely that the scheduler for the PIC port will get stopped
253          * once running. When called a reset is done which is probably the
254          * most valid action.
255          */
256         _Pragma(asmline reset);
257 }
258
259 /*-----------------------------------------------------------*/
260
261 /*
262  * Manual context switch.  This is similar to the tick context switch,
263  * but does not increment the tick count.  It must be identical to the
264  * tick context switch in how it stores the stack of a task.
265  */
266 void vPortYield( void )
267 {
268         /*
269          * Save the context of the current task.
270          */
271         portSAVE_CONTEXT( portINTERRUPTS_UNCHANGED );
272
273         /*
274          * Switch to the highest priority task that is ready to run.
275          */
276         vTaskSwitchContext();
277
278         /*
279          * Start executing the task we have just switched to.
280          */
281         portRESTORE_CONTEXT();
282 }
283 /*-----------------------------------------------------------*/
284
285 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
286
287         void *pvPortMalloc( uint16_t usWantedSize )
288         {
289         void *pvReturn;
290
291                 vTaskSuspendAll();
292                 {
293                         pvReturn = malloc( ( malloc_t ) usWantedSize );
294                 }
295                 xTaskResumeAll();
296
297                 return pvReturn;
298         }
299
300 #endif /* configSUPPORT_STATIC_ALLOCATION */
301
302 /*-----------------------------------------------------------*/
303
304 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
305
306         void vPortFree( void *pv )
307         {
308                 if( pv )
309                 {
310                         vTaskSuspendAll();
311                         {
312                                 free( pv );
313                         }
314                         xTaskResumeAll();
315                 }
316         }
317
318 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */