2 FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\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
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
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
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
28 ***************************************************************************
\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
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
40 ***************************************************************************
\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
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
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
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
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
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
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
73 /*-----------------------------------------------------------
\r
74 * Implementation of functions defined in portable.h for the RISC-V port.
\r
75 *----------------------------------------------------------*/
\r
77 /* Scheduler includes. */
\r
78 #include "FreeRTOS.h"
\r
80 #include "portmacro.h"
\r
82 #include "riscv_hal.h"
\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
100 /* Contains context when starting scheduler, save all 31 registers */
\r
101 #ifdef __gracefulExit
\r
102 BaseType_t xStartContext[31] = {0};
\r
110 }riscv_machine_timer_t;
\r
112 static volatile riscv_machine_timer_t *mtime = (riscv_machine_timer_t *)0x4400BFF8;
\r
114 static volatile riscv_machine_timer_t *mtimecmp = (riscv_machine_timer_t *)0x44004000;
\r
117 * Setup the timer to generate the tick interrupts.
\r
119 void vPortSetupTimer( void );
\r
122 * Set the next interval for the timer
\r
124 static void prvSetNextTimerInterrupt( void );
\r
127 * Used to catch tasks that attempt to return from their implementing function.
\r
129 static void prvTaskExitError( void );
\r
131 void vPortEnterCritical( void )
\r
133 portDISABLE_INTERRUPTS();
\r
134 uxCriticalNesting++;
\r
136 /*-----------------------------------------------------------*/
\r
138 void vPortExitCritical( void )
\r
140 uxCriticalNesting--;
\r
141 if( uxCriticalNesting == 0 )
\r
143 portENABLE_INTERRUPTS();
\r
146 /*-----------------------------------------------------------*/
\r
148 /* Sets the next timer interrupt
\r
149 * Reads previous timer compare register, and adds tickrate */
\r
150 static void prvSetNextTimerInterrupt(void)
\r
154 time = mtime->val_low;
\r
155 time |= ((uint64_t)mtime->val_high << 32);
\r
157 time += (configCPU_CLOCK_HZ / configTICK_RATE_HZ);
\r
159 mtimecmp->val_low = (uint32_t)(time & 0xFFFFFFFF);
\r
160 mtimecmp->val_high = (uint32_t)((time >> 32) & 0xFFFFFFFF);
\r
162 /* Enable timer interrupt */
\r
163 __asm volatile("csrs mie,%0"::"r"(0x80));
\r
165 /*-----------------------------------------------------------*/
\r
167 /* Sets and enable the timer interrupt */
\r
168 void vPortSetupTimer(void)
\r
172 time = mtime->val_low;
\r
173 time |= ((uint64_t)mtime->val_high << 32);
\r
175 time += (configCPU_CLOCK_HZ / configTICK_RATE_HZ);
\r
177 mtimecmp->val_low = (uint32_t)(time & 0xFFFFFFFF);
\r
178 mtimecmp->val_high = (uint32_t)((time >> 32) & 0xFFFFFFFF);
\r
181 /* Enable timer interrupt */
\r
182 __asm volatile("csrs mie,%0"::"r"(0x80));
\r
184 /*-----------------------------------------------------------*/
\r
186 void prvTaskExitError( void )
\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
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
198 /*-----------------------------------------------------------*/
\r
200 /* Clear current interrupt mask and set given mask */
\r
201 void vPortClearInterruptMask(int mask)
\r
203 __asm volatile("csrw mie, %0"::"r"(mask));
\r
205 /*-----------------------------------------------------------*/
\r
207 /* Set interrupt mask and return current interrupt enable register */
\r
208 int vPortSetInterruptMask(void)
\r
211 __asm volatile("csrr %0,mie":"=r"(ret));
\r
212 __asm volatile("csrc mie,%0"::"i"(7));
\r
217 * See header file for description.
\r
219 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
\r
221 /* Simulate the stack frame as it would be created by a context switch
\r
223 register int *tp asm("x3");
\r
225 *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */
\r
226 pxTopOfStack -= 22;
\r
227 *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */
\r
229 *pxTopOfStack = (portSTACK_TYPE)tp; /* Register thread pointer */
\r
231 *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
\r
233 return pxTopOfStack;
\r
235 /*-----------------------------------------------------------*/
\r
237 void vPortSysTickHandler( void )
\r
241 __asm volatile("lw t0, pxCurrentTCB");
\r
242 __asm volatile("sw a2, 0x0(t0)");
\r
245 /* Increment the RTOS tick. */
\r
246 prvSetNextTimerInterrupt();
\r
249 if( xTaskIncrementTick() != pdFALSE )
\r
251 vTaskSwitchContext();
\r
254 /*Restore Context*/
\r
256 __asm volatile("lw sp, pxCurrentTCB");
\r
257 __asm volatile("lw sp, 0x0(sp)");
\r
259 __asm volatile("lw t0, 31 * 4(sp)");
\r
260 __asm volatile("csrw mepc, t0");
\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
292 __asm volatile("addi sp, sp, 4 * 32");
\r
294 __asm volatile("mret");
\r
297 uint32_t g_startscheduler = 0;
\r
298 BaseType_t xPortStartScheduler( void )
\r
301 uxCriticalNesting = 0;
\r
302 g_startscheduler = 1;
\r
305 raise_soft_interrupt();
\r
307 /*Should not get here*/
\r
311 void Software_IRQHandler(void)
\r
313 if(1 == g_startscheduler)
\r
315 g_startscheduler = 2; //skip the save n switch context first time when scheduler is starting.
\r
321 __asm volatile("lw t0, pxCurrentTCB");
\r
322 __asm volatile("sw a2, 0x0(t0)");
\r
325 vTaskSwitchContext();
\r
328 /*Restore Context*/
\r
330 __asm volatile("lw sp, pxCurrentTCB");
\r
331 __asm volatile("lw sp, 0x0(sp)");
\r
333 __asm volatile("lw t0, 31 * 4(sp)");
\r
334 __asm volatile("csrw mepc, t0");
\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
366 __asm volatile("addi sp, sp, 4 * 32");
\r
368 //PRCI->MSIP[0] = 0x00;
\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
377 __asm volatile("mret");
\r
381 void vPortYield( void )
\r
383 raise_soft_interrupt();
\r