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