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