]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/ThirdParty/GCC/RISC-V/port.c
3d96ce8aababcf4b0993b78277ac3f2b5127ff31
[freertos] / FreeRTOS / Source / portable / ThirdParty / GCC / RISC-V / port.c
1 /*\r
2     FreeRTOS V8.2.3 - 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 and was contributed\r
8     to the project by Technolution B.V. (www.technolution.nl,\r
9     freertos-riscv@technolution.eu) under the terms of the FreeRTOS\r
10     contributors license.\r
11 \r
12     FreeRTOS is free software; you can redistribute it and/or modify it under\r
13     the terms of the GNU General Public License (version 2) as published by the\r
14     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
15 \r
16     ***************************************************************************\r
17     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
18     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
19     >>!   obliged to provide the source code for proprietary components     !<<\r
20     >>!   outside of the FreeRTOS kernel.                                   !<<\r
21     ***************************************************************************\r
22 \r
23     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
24     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
25     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
26     link: http://www.freertos.org/a00114.html\r
27 \r
28     ***************************************************************************\r
29      *                                                                       *\r
30      *    FreeRTOS provides completely free yet professionally developed,    *\r
31      *    robust, strictly quality controlled, supported, and cross          *\r
32      *    platform software that is more than just the market leader, it     *\r
33      *    is the industry's de facto standard.                               *\r
34      *                                                                       *\r
35      *    Help yourself get started quickly while simultaneously helping     *\r
36      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
37      *    tutorial book, reference manual, or both:                          *\r
38      *    http://www.FreeRTOS.org/Documentation                              *\r
39      *                                                                       *\r
40     ***************************************************************************\r
41 \r
42     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
43     the FAQ page "My application does not run, what could be wrong?".  Have you\r
44     defined configASSERT()?\r
45 \r
46     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
47     embedded software for free we request you assist our global community by\r
48     participating in the support forum.\r
49 \r
50     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
51     be as productive as possible as early as possible.  Now you can receive\r
52     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
53     Ltd, and the world's leading authority on the world's leading RTOS.\r
54 \r
55     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
56     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
57     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
58 \r
59     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
60     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
61 \r
62     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
63     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
64     licenses offer ticketed support, indemnification and commercial middleware.\r
65 \r
66     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
67     engineered and independently SIL3 certified version for use in safety and\r
68     mission critical applications that require provable dependability.\r
69 \r
70     1 tab == 4 spaces!\r
71 */\r
72 \r
73 /*-----------------------------------------------------------\r
74  * Implementation of functions defined in portable.h for the RISC-V port.\r
75  *----------------------------------------------------------*/\r
76 \r
77 /* Scheduler includes. */\r
78 #include "FreeRTOS.h"\r
79 #include "task.h"\r
80 #include "portmacro.h"\r
81 \r
82 #include "riscv_hal.h"\r
83 \r
84 #ifdef __riscv64\r
85 # define STORE    sd\r
86 # define LOAD     ld\r
87 # define REGBYTES 8\r
88 #else\r
89 # define STORE    sw\r
90 # define LOAD     lw\r
91 # define REGBYTES 4\r
92 #endif\r
93 /* A variable is used to keep track of the critical section nesting.  This\r
94 variable has to be stored as part of the task context and must be initialized to\r
95 a non zero value to ensure interrupts don't inadvertently become unmasked before\r
96 the scheduler starts.  As it is stored as part of the task context it will\r
97 automatically be set to 0 when the first task is started. */\r
98 static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;\r
99 \r
100 /* Contains context when starting scheduler, save all 31 registers */\r
101 #ifdef __gracefulExit\r
102 BaseType_t xStartContext[31] = {0};\r
103 #endif\r
104 \r
105 \r
106 typedef struct\r
107 {\r
108         uint32_t val_low;\r
109         uint32_t val_high;\r
110 }riscv_machine_timer_t;\r
111 \r
112 static volatile riscv_machine_timer_t *mtime = (riscv_machine_timer_t *)0x4400BFF8;\r
113 \r
114 static volatile riscv_machine_timer_t *mtimecmp = (riscv_machine_timer_t *)0x44004000;\r
115 \r
116 /*\r
117  * Setup the timer to generate the tick interrupts.\r
118  */\r
119 void vPortSetupTimer( void );\r
120 \r
121 /*\r
122  * Set the next interval for the timer\r
123  */\r
124 static void prvSetNextTimerInterrupt( void );\r
125 \r
126 /*\r
127  * Used to catch tasks that attempt to return from their implementing function.\r
128  */\r
129 static void prvTaskExitError( void );\r
130 \r
131 void vPortEnterCritical( void )\r
132 {\r
133         portDISABLE_INTERRUPTS();\r
134         uxCriticalNesting++;\r
135 }\r
136 /*-----------------------------------------------------------*/\r
137 \r
138 void vPortExitCritical( void )\r
139 {\r
140         uxCriticalNesting--;\r
141         if( uxCriticalNesting == 0 )\r
142         {\r
143                 portENABLE_INTERRUPTS();\r
144         }\r
145 }\r
146 /*-----------------------------------------------------------*/\r
147 \r
148 /* Sets the next timer interrupt\r
149  * Reads previous timer compare register, and adds tickrate */\r
150 static void prvSetNextTimerInterrupt(void)\r
151 {\r
152         uint64_t time;\r
153 \r
154         time = mtime->val_low;\r
155         time |= ((uint64_t)mtime->val_high << 32);\r
156 \r
157         time += (configCPU_CLOCK_HZ / configTICK_RATE_HZ);\r
158 \r
159         mtimecmp->val_low = (uint32_t)(time & 0xFFFFFFFF);\r
160         mtimecmp->val_high = (uint32_t)((time >> 32) & 0xFFFFFFFF);\r
161 \r
162         /* Enable timer interrupt */\r
163         __asm volatile("csrs mie,%0"::"r"(0x80));\r
164 }\r
165 /*-----------------------------------------------------------*/\r
166 \r
167 /* Sets and enable the timer interrupt */\r
168 void vPortSetupTimer(void)\r
169 {\r
170         uint64_t time;\r
171 \r
172         time = mtime->val_low;\r
173         time |= ((uint64_t)mtime->val_high << 32);\r
174 \r
175         time += (configCPU_CLOCK_HZ / configTICK_RATE_HZ);\r
176 \r
177         mtimecmp->val_low = (uint32_t)(time & 0xFFFFFFFF);\r
178         mtimecmp->val_high = (uint32_t)((time >> 32) & 0xFFFFFFFF);\r
179 \r
180 \r
181         /* Enable timer interrupt */\r
182         __asm volatile("csrs mie,%0"::"r"(0x80));\r
183 }\r
184 /*-----------------------------------------------------------*/\r
185 \r
186 void prvTaskExitError( void )\r
187 {\r
188         /* A function that implements a task must not exit or attempt to return to\r
189         its caller as there is nothing to return to.  If a task wants to exit it\r
190         should instead call vTaskDelete( NULL ).\r
191 \r
192         Artificially force an assert() to be triggered if configASSERT() is\r
193         defined, then stop here so application writers can catch the error. */\r
194         configASSERT( uxCriticalNesting == ~0UL );\r
195         portDISABLE_INTERRUPTS();\r
196         for( ;; );\r
197 }\r
198 /*-----------------------------------------------------------*/\r
199 \r
200 /* Clear current interrupt mask and set given mask */\r
201 void vPortClearInterruptMask(int mask)\r
202 {\r
203         __asm volatile("csrw mie, %0"::"r"(mask));\r
204 }\r
205 /*-----------------------------------------------------------*/\r
206 \r
207 /* Set interrupt mask and return current interrupt enable register */\r
208 int vPortSetInterruptMask(void)\r
209 {\r
210         int ret;\r
211         __asm volatile("csrr %0,mie":"=r"(ret));\r
212         __asm volatile("csrc mie,%0"::"i"(7));\r
213         return ret;\r
214 }\r
215 \r
216 /*\r
217  * See header file for description.\r
218  */\r
219 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
220 {\r
221         /* Simulate the stack frame as it would be created by a context switch\r
222         interrupt. */\r
223         register int *tp asm("x3");\r
224         pxTopOfStack--;\r
225         *pxTopOfStack = (portSTACK_TYPE)pxCode;                 /* Start address */\r
226         pxTopOfStack -= 22;\r
227         *pxTopOfStack = (portSTACK_TYPE)pvParameters;   /* Register a0 */\r
228         pxTopOfStack -= 6;\r
229         *pxTopOfStack = (portSTACK_TYPE)tp; /* Register thread pointer */\r
230         pxTopOfStack -= 3;\r
231         *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */\r
232         \r
233         return pxTopOfStack;\r
234 }\r
235 /*-----------------------------------------------------------*/\r
236 \r
237 void vPortSysTickHandler( void )\r
238 {\r
239         /*Save Context*/\r
240         {\r
241                 __asm volatile("lw      t0, pxCurrentTCB");\r
242                 __asm volatile("sw      a2, 0x0(t0)");\r
243         }\r
244 \r
245         /* Increment the RTOS tick. */\r
246         prvSetNextTimerInterrupt();\r
247 \r
248         /*Switch task */\r
249         if( xTaskIncrementTick() != pdFALSE )\r
250         {\r
251                 vTaskSwitchContext();\r
252         }\r
253 \r
254         /*Restore Context*/\r
255         {\r
256                 __asm volatile("lw      sp, pxCurrentTCB");\r
257                 __asm volatile("lw      sp, 0x0(sp)");\r
258 \r
259                 __asm volatile("lw      t0, 31 * 4(sp)");\r
260                 __asm volatile("csrw    mepc, t0");\r
261 \r
262                 __asm volatile("lw      x1, 0x0(sp)");\r
263                 __asm volatile("lw   x4, 3 * 4(sp)");\r
264                 __asm volatile("lw   x5, 4 * 4(sp)");\r
265                 __asm volatile("lw   x6, 5 * 4(sp)");\r
266                 __asm volatile("lw   x7, 6 * 4(sp)");\r
267                 __asm volatile("lw   x8, 7 * 4(sp)");\r
268                 __asm volatile("lw   x9, 8 * 4(sp)");\r
269                 __asm volatile("lw   x10, 9 * 4(sp)");\r
270                 __asm volatile("lw   x11, 10 * 4(sp)");\r
271                 __asm volatile("lw   x12, 11 * 4(sp)");\r
272                 __asm volatile("lw   x13, 12 * 4(sp)");\r
273                 __asm volatile("lw   x14, 13 * 4(sp)");\r
274                 __asm volatile("lw   x15, 14 * 4(sp)");\r
275                 __asm volatile("lw   x16, 15 * 4(sp)");\r
276                 __asm volatile("lw   x17, 16 * 4(sp)");\r
277                 __asm volatile("lw   x18, 17 * 4(sp)");\r
278                 __asm volatile("lw   x19, 18 * 4(sp)");\r
279                 __asm volatile("lw   x20, 19 * 4(sp)");\r
280                 __asm volatile("lw   x21, 20 * 4(sp)");\r
281                 __asm volatile("lw   x22, 21 * 4(sp)");\r
282                 __asm volatile("lw   x23, 22 * 4(sp)");\r
283                 __asm volatile("lw   x24, 23 * 4(sp)");\r
284                 __asm volatile("lw   x25, 24 * 4(sp)");\r
285                 __asm volatile("lw   x26, 25 * 4(sp)");\r
286                 __asm volatile("lw   x27, 26 * 4(sp)");\r
287                 __asm volatile("lw   x28, 27 * 4(sp)");\r
288                 __asm volatile("lw   x29, 28 * 4(sp)");\r
289                 __asm volatile("lw   x30, 29 * 4(sp)");\r
290                 __asm volatile("lw   x31, 30 * 4(sp)");\r
291 \r
292                 __asm volatile("addi    sp, sp, 4 * 32");\r
293 \r
294                 __asm volatile("mret");\r
295         }\r
296 }\r
297 uint32_t g_startscheduler = 0;\r
298 BaseType_t xPortStartScheduler( void )\r
299 {\r
300         vPortSetupTimer();\r
301         uxCriticalNesting = 0;\r
302         g_startscheduler = 1;\r
303         __enable_irq();\r
304 \r
305         raise_soft_interrupt();\r
306 \r
307         /*Should not get here*/\r
308         return pdFALSE;\r
309 }\r
310 \r
311 void Software_IRQHandler(void)\r
312 {\r
313         if(1 == g_startscheduler)\r
314         {\r
315                 g_startscheduler = 2; //skip the save n switch context first time when scheduler is starting.\r
316         }\r
317         else\r
318         {\r
319                 /*Save Context*/\r
320                 {\r
321                         __asm volatile("lw      t0, pxCurrentTCB");\r
322                         __asm volatile("sw      a2, 0x0(t0)");\r
323                 }\r
324 \r
325                 vTaskSwitchContext();\r
326         }\r
327 \r
328         /*Restore Context*/\r
329         {\r
330                 __asm volatile("lw      sp, pxCurrentTCB");\r
331                 __asm volatile("lw      sp, 0x0(sp)");\r
332 \r
333                 __asm volatile("lw      t0, 31 * 4(sp)");\r
334                 __asm volatile("csrw    mepc, t0");\r
335 \r
336                 __asm volatile("lw      x1, 0x0(sp)");\r
337                 __asm volatile("lw   x4, 3 * 4(sp)");\r
338                 __asm volatile("lw   x5, 4 * 4(sp)");\r
339                 __asm volatile("lw   x6, 5 * 4(sp)");\r
340                 __asm volatile("lw   x7, 6 * 4(sp)");\r
341                 __asm volatile("lw   x8, 7 * 4(sp)");\r
342                 __asm volatile("lw   x9, 8 * 4(sp)");\r
343                 __asm volatile("lw   x10, 9 * 4(sp)");\r
344                 __asm volatile("lw   x11, 10 * 4(sp)");\r
345                 __asm volatile("lw   x12, 11 * 4(sp)");\r
346                 __asm volatile("lw   x13, 12 * 4(sp)");\r
347                 __asm volatile("lw   x14, 13 * 4(sp)");\r
348                 __asm volatile("lw   x15, 14 * 4(sp)");\r
349                 __asm volatile("lw   x16, 15 * 4(sp)");\r
350                 __asm volatile("lw   x17, 16 * 4(sp)");\r
351                 __asm volatile("lw   x18, 17 * 4(sp)");\r
352                 __asm volatile("lw   x19, 18 * 4(sp)");\r
353                 __asm volatile("lw   x20, 19 * 4(sp)");\r
354                 __asm volatile("lw   x21, 20 * 4(sp)");\r
355                 __asm volatile("lw   x22, 21 * 4(sp)");\r
356                 __asm volatile("lw   x23, 22 * 4(sp)");\r
357                 __asm volatile("lw   x24, 23 * 4(sp)");\r
358                 __asm volatile("lw   x25, 24 * 4(sp)");\r
359                 __asm volatile("lw   x26, 25 * 4(sp)");\r
360                 __asm volatile("lw   x27, 26 * 4(sp)");\r
361                 __asm volatile("lw   x28, 27 * 4(sp)");\r
362                 __asm volatile("lw   x29, 28 * 4(sp)");\r
363                 __asm volatile("lw   x30, 29 * 4(sp)");\r
364                 __asm volatile("lw   x31, 30 * 4(sp)");\r
365 \r
366                 __asm volatile("addi    sp, sp, 4 * 32");\r
367 \r
368                 //PRCI->MSIP[0] = 0x00;\r
369 \r
370                 __asm volatile("addi sp, sp, -1*4");\r
371                 __asm volatile("sw t0, 0(sp)");\r
372                 __asm volatile("li t0, 0x44000000");    // address of PRCI->MSIP[0]\r
373                 __asm volatile("sw zero,0(t0)");\r
374                 __asm volatile("lw t0, 0(sp)");\r
375                 __asm volatile("addi sp, sp, 1*4");\r
376 \r
377                 __asm volatile("mret");\r
378         }\r
379 }\r
380 \r
381 void vPortYield( void )\r
382 {\r
383         raise_soft_interrupt();\r
384 }\r
385 \r