Skip to content

Commit 0037a6c

Browse files
authored
RISC-V: Add RV32E / FPU support for GCC (#140)
* Change vPortSetupTimerInterrupt in order to have 64bits access on rv64 * Support RV32E - RISC-V architecture (GCC) Signed-off-by: Emmanuel Puerto <emmanuel.puerto@sifive.com> * Support FPU - RISC-V architecture (GCC) Signed-off-by: Emmanuel Puerto <emmanuel.puerto@sifive.com> * Fix interrupt managment and FPU initialization
1 parent 524e78d commit 0037a6c

File tree

2 files changed

+697
-301
lines changed

2 files changed

+697
-301
lines changed

portable/GCC/RISC-V/port.c

Lines changed: 91 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
* 1 tab == 4 spaces!
2626
*/
2727

28-
/*-----------------------------------------------------------
29-
* Implementation of functions defined in portable.h for the RISC-V RV32 port.
30-
*----------------------------------------------------------*/
28+
/* ------------------------------------------------------------------
29+
* This file is part of the FreeRTOS distribution and was contributed
30+
* to the project by SiFive
31+
* ------------------------------------------------------------------
32+
*/
3133

3234
/* Scheduler includes. */
3335
#include "FreeRTOS.h"
@@ -118,31 +120,69 @@ task stack, not the ISR stack). */
118120

119121
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
120122

121-
void vPortSetupTimerInterrupt( void )
122-
{
123-
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
124-
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
125-
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
126-
volatile uint32_t ulHartId;
127-
128-
__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
129-
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
130-
131-
do
132-
{
133-
ulCurrentTimeHigh = *pulTimeHigh;
134-
ulCurrentTimeLow = *pulTimeLow;
135-
} while( ulCurrentTimeHigh != *pulTimeHigh );
136-
137-
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
138-
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
139-
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
140-
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
141-
*pullMachineTimerCompareRegister = ullNextTime;
142-
143-
/* Prepare the time to use after the next tick interrupt. */
144-
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
145-
}
123+
#if( __riscv_xlen == 32 )
124+
void vPortSetupTimerInterrupt( void )
125+
{
126+
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
127+
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
128+
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
129+
volatile uint32_t * pulTimeCompareRegisterHigh;
130+
volatile uint32_t * pulTimeCompareRegisterLow;
131+
132+
volatile uint32_t ulHartId;
133+
134+
__asm volatile ( "csrr %0, mhartid" : "=r" ( ulHartId ) );
135+
136+
/* pullMachineTimerCompareRegister is used by freertos_risc_v_trap_handler */
137+
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
138+
pulTimeCompareRegisterLow = ( volatile uint32_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
139+
pulTimeCompareRegisterHigh = ( volatile uint32_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) + 4UL );
140+
141+
do
142+
{
143+
ulCurrentTimeHigh = *pulTimeHigh;
144+
ulCurrentTimeLow = *pulTimeLow;
145+
} while( ulCurrentTimeHigh != *pulTimeHigh );
146+
147+
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
148+
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
149+
ullNextTime |= (( uint64_t ) ulCurrentTimeLow );
150+
ullNextTime += (( uint64_t ) uxTimerIncrementsForOneTick );
151+
/* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
152+
* and are NOT internally latched for multiword transfers.
153+
* Need to be careful about sequencing to avoid triggering
154+
* spurious interrupts: For that set the high word to a max
155+
* value first.
156+
*/
157+
*pulTimeCompareRegisterHigh = 0xFFFFFFFF;
158+
*pulTimeCompareRegisterLow = (uint32_t)( ullNextTime );
159+
*pulTimeCompareRegisterHigh = (uint32_t)( ullNextTime >> 32ULL );
160+
161+
/* Prepare the time to use after the next tick interrupt. */
162+
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
163+
}
164+
#endif /* __riscv_xlen == 32 */
165+
166+
#if( __riscv_xlen == 64 )
167+
void vPortSetupTimerInterrupt( void )
168+
{
169+
volatile uint32_t * const pulTime = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
170+
171+
volatile uint32_t ulHartId;
172+
173+
__asm volatile ( "csrr %0, mhartid" : "=r" ( ulHartId ) );
174+
175+
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
176+
177+
ullNextTime = *pulTime;
178+
179+
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
180+
*pullMachineTimerCompareRegister = ullNextTime;
181+
182+
/* Prepare the time to use after the next tick interrupt. */
183+
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
184+
}
185+
#endif /* __riscv_xlen == 64 */
146186

147187
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
148188
/*-----------------------------------------------------------*/
@@ -178,20 +218,7 @@ extern void xPortStartFirstTask( void );
178218
configure whichever clock is to be used to generate the tick interrupt. */
179219
vPortSetupTimerInterrupt();
180220

181-
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
182-
{
183-
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
184-
for external interrupt. _RB_ What happens here when mtime is not present as
185-
with pulpino? */
186-
__asm volatile( "csrs mie, %0" :: "r"(0x880) );
187-
}
188-
#else
189-
{
190-
/* Enable external interrupts. */
191-
__asm volatile( "csrs mie, %0" :: "r"(0x800) );
192-
}
193-
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
194-
221+
/* Enabling mtime and external interrupts will be made into xPortStartFirstTask function */
195222
xPortStartFirstTask();
196223

197224
/* Should not get here as after calling xPortStartFirstTask() only tasks
@@ -205,8 +232,26 @@ void vPortEndScheduler( void )
205232
/* Not implemented. */
206233
for( ;; );
207234
}
235+
/*-----------------------------------------------------------*/
208236

209-
210-
211-
212-
237+
#if( configENABLE_FPU == 1 )
238+
void vPortSetupFPU( void )
239+
{
240+
#ifdef __riscv_fdiv
241+
__asm__ __volatile__ (
242+
"csrr t0, misa \n" /* Get misa */
243+
"li t1, 0x10028 \n" /* 0x10028 = Q,F,D Quad, Single or Double precission floating point */
244+
"and t0, t0, t1 \n"
245+
"beqz t0, 1f \n" /* check if Q,F or D is present into misa */
246+
"csrr t0, mstatus \n" /* Floating point unit is present so need to put it into initial state */
247+
"lui t1, 0x2 \n" /* t1 = 0x1 << 12 */
248+
"or t0, t0, t1 \n"
249+
"csrw mstatus, t0 \n" /* Set FS to initial state */
250+
"csrwi fcsr, 0 \n" /* Clear Floating-point Control and Status Register */
251+
"1: \n"
252+
:::
253+
);
254+
#endif /* __riscv_fdiv */
255+
}
256+
#endif /* configENABLE_FPU */
257+
/*-----------------------------------------------------------*/

0 commit comments

Comments
 (0)