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