mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	This reverts commit 0037a6c574f43937d181d4d47fdc2bdd562bbcc3.
This commit is contained in:
		
							parent
							
								
									cfb51b3db8
								
							
						
					
					
						commit
						2f14899ce8
					
				@ -25,11 +25,9 @@
 | 
			
		||||
 * 1 tab == 4 spaces!
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------
 | 
			
		||||
 * This file is part of the FreeRTOS distribution and was contributed
 | 
			
		||||
 * to the project by SiFive
 | 
			
		||||
 * ------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
/*-----------------------------------------------------------
 | 
			
		||||
 * Implementation of functions defined in portable.h for the RISC-V RV32 port.
 | 
			
		||||
 *----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Scheduler includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
@ -120,69 +118,31 @@ task stack, not the ISR stack). */
 | 
			
		||||
 | 
			
		||||
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
 | 
			
		||||
 | 
			
		||||
    #if( __riscv_xlen == 32 )
 | 
			
		||||
        void vPortSetupTimerInterrupt( void )
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
 | 
			
		||||
            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. */
 | 
			
		||||
            volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
 | 
			
		||||
            volatile uint32_t * pulTimeCompareRegisterHigh;
 | 
			
		||||
            volatile uint32_t * pulTimeCompareRegisterLow;
 | 
			
		||||
	void vPortSetupTimerInterrupt( void )
 | 
			
		||||
	{
 | 
			
		||||
	uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
 | 
			
		||||
	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. */
 | 
			
		||||
	volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
 | 
			
		||||
	volatile uint32_t ulHartId;
 | 
			
		||||
 | 
			
		||||
            volatile uint32_t ulHartId;
 | 
			
		||||
		__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
 | 
			
		||||
		pullMachineTimerCompareRegister  = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
 | 
			
		||||
 | 
			
		||||
            __asm volatile ( "csrr %0, mhartid" : "=r" ( ulHartId ) );
 | 
			
		||||
		do
 | 
			
		||||
		{
 | 
			
		||||
			ulCurrentTimeHigh = *pulTimeHigh;
 | 
			
		||||
			ulCurrentTimeLow = *pulTimeLow;
 | 
			
		||||
		} while( ulCurrentTimeHigh != *pulTimeHigh );
 | 
			
		||||
 | 
			
		||||
			/* pullMachineTimerCompareRegister is used by freertos_risc_v_trap_handler */
 | 
			
		||||
            pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
 | 
			
		||||
            pulTimeCompareRegisterLow = ( volatile uint32_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
 | 
			
		||||
            pulTimeCompareRegisterHigh = ( volatile uint32_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) + 4UL );
 | 
			
		||||
		ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
 | 
			
		||||
		ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
 | 
			
		||||
		ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
 | 
			
		||||
		ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
 | 
			
		||||
		*pullMachineTimerCompareRegister = ullNextTime;
 | 
			
		||||
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                ulCurrentTimeHigh = *pulTimeHigh;
 | 
			
		||||
                ulCurrentTimeLow = *pulTimeLow;
 | 
			
		||||
            } while( ulCurrentTimeHigh != *pulTimeHigh );
 | 
			
		||||
 | 
			
		||||
            ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
 | 
			
		||||
            ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
 | 
			
		||||
            ullNextTime |= (( uint64_t ) ulCurrentTimeLow );
 | 
			
		||||
            ullNextTime += (( uint64_t ) uxTimerIncrementsForOneTick );
 | 
			
		||||
            /* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
 | 
			
		||||
             * and are NOT internally latched for multiword transfers.
 | 
			
		||||
             * Need to be careful about sequencing to avoid triggering
 | 
			
		||||
             * spurious interrupts: For that set the high word to a max
 | 
			
		||||
             * value first.
 | 
			
		||||
             */
 | 
			
		||||
            *pulTimeCompareRegisterHigh = 0xFFFFFFFF;
 | 
			
		||||
            *pulTimeCompareRegisterLow = (uint32_t)( ullNextTime );
 | 
			
		||||
            *pulTimeCompareRegisterHigh = (uint32_t)( ullNextTime >> 32ULL );
 | 
			
		||||
 | 
			
		||||
            /* Prepare the time to use after the next tick interrupt. */
 | 
			
		||||
            ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
 | 
			
		||||
        }
 | 
			
		||||
    #endif /* __riscv_xlen == 32 */
 | 
			
		||||
 | 
			
		||||
    #if( __riscv_xlen == 64 )
 | 
			
		||||
        void vPortSetupTimerInterrupt( void )
 | 
			
		||||
        {
 | 
			
		||||
            volatile uint32_t * const pulTime = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
 | 
			
		||||
 | 
			
		||||
            volatile uint32_t ulHartId;
 | 
			
		||||
 | 
			
		||||
            __asm volatile ( "csrr %0, mhartid" : "=r" ( ulHartId ) );
 | 
			
		||||
 | 
			
		||||
            pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
 | 
			
		||||
 | 
			
		||||
            ullNextTime = *pulTime;
 | 
			
		||||
 | 
			
		||||
            ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
 | 
			
		||||
            *pullMachineTimerCompareRegister = ullNextTime;
 | 
			
		||||
 | 
			
		||||
            /* Prepare the time to use after the next tick interrupt. */
 | 
			
		||||
            ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
 | 
			
		||||
        }
 | 
			
		||||
    #endif /* __riscv_xlen == 64 */
 | 
			
		||||
		/* Prepare the time to use after the next tick interrupt. */
 | 
			
		||||
		ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -218,7 +178,20 @@ extern void xPortStartFirstTask( void );
 | 
			
		||||
	configure whichever clock is to be used to generate the tick interrupt. */
 | 
			
		||||
	vPortSetupTimerInterrupt();
 | 
			
		||||
 | 
			
		||||
    /* Enabling mtime and external interrupts will be made into xPortStartFirstTask function */
 | 
			
		||||
	#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
 | 
			
		||||
	{
 | 
			
		||||
		/* Enable mtime and external interrupts.  1<<7 for timer interrupt, 1<<11
 | 
			
		||||
		for external interrupt.  _RB_ What happens here when mtime is not present as
 | 
			
		||||
		with pulpino? */
 | 
			
		||||
		__asm volatile( "csrs mie, %0" :: "r"(0x880) );
 | 
			
		||||
	}
 | 
			
		||||
	#else
 | 
			
		||||
	{
 | 
			
		||||
		/* Enable external interrupts. */
 | 
			
		||||
		__asm volatile( "csrs mie, %0" :: "r"(0x800) );
 | 
			
		||||
	}
 | 
			
		||||
	#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
 | 
			
		||||
 | 
			
		||||
	xPortStartFirstTask();
 | 
			
		||||
 | 
			
		||||
	/* Should not get here as after calling xPortStartFirstTask() only tasks
 | 
			
		||||
@ -232,26 +205,8 @@ void vPortEndScheduler( void )
 | 
			
		||||
	/* Not implemented. */
 | 
			
		||||
	for( ;; );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( configENABLE_FPU == 1 )
 | 
			
		||||
	void vPortSetupFPU( void )
 | 
			
		||||
	{
 | 
			
		||||
		#ifdef __riscv_fdiv
 | 
			
		||||
		__asm__ __volatile__ (
 | 
			
		||||
			"csrr t0, misa \n"			/* Get misa */
 | 
			
		||||
			"li   t1, 0x10028 \n"		/* 0x10028 = Q,F,D Quad, Single or Double precission floating point */
 | 
			
		||||
			"and  t0, t0, t1 \n"
 | 
			
		||||
			"beqz t0, 1f \n"			/* check if Q,F or D is present into misa */
 | 
			
		||||
			"csrr t0, mstatus \n"		/* Floating point unit is present so need to put it into initial state */
 | 
			
		||||
			"lui  t1, 0x2 \n"			/* t1 =  0x1 << 12 */
 | 
			
		||||
			"or   t0, t0, t1 \n"
 | 
			
		||||
			"csrw mstatus, t0 \n"		/* Set FS to initial state */
 | 
			
		||||
			"csrwi fcsr, 0 \n"			/* Clear Floating-point Control and Status Register */
 | 
			
		||||
			"1: \n"
 | 
			
		||||
			:::
 | 
			
		||||
		);
 | 
			
		||||
		#endif /* __riscv_fdiv */
 | 
			
		||||
	}
 | 
			
		||||
#endif /* configENABLE_FPU */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -55,56 +55,17 @@
 | 
			
		||||
 * registers.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------
 | 
			
		||||
 * This file is part of the FreeRTOS distribution and was contributed
 | 
			
		||||
 * to the project by SiFive
 | 
			
		||||
 * ------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if( __riscv_xlen == 64 )
 | 
			
		||||
#if __riscv_xlen == 64
 | 
			
		||||
	#define portWORD_SIZE 8
 | 
			
		||||
	#define store_x sd
 | 
			
		||||
	#define load_x ld
 | 
			
		||||
#elif( __riscv_xlen == 32 )
 | 
			
		||||
#elif __riscv_xlen == 32
 | 
			
		||||
	#define store_x sw
 | 
			
		||||
	#define load_x lw
 | 
			
		||||
	#define portWORD_SIZE 4
 | 
			
		||||
#else
 | 
			
		||||
	#error Assembler did not define __riscv_xlen
 | 
			
		||||
#endif /* ( __riscv_xlen == xx ) */
 | 
			
		||||
 | 
			
		||||
/* Nb registers to save */
 | 
			
		||||
#ifdef __riscv_32e
 | 
			
		||||
#define portasmNB_REGS_SAVED			(16)
 | 
			
		||||
#else
 | 
			
		||||
#define portasmNB_REGS_SAVED			(32)
 | 
			
		||||
#endif /* __riscv_32e */
 | 
			
		||||
 | 
			
		||||
#define portWORD_SIZE					(__riscv_xlen / 8)
 | 
			
		||||
 | 
			
		||||
/* Number of FPU register */
 | 
			
		||||
#ifdef __riscv_fdiv
 | 
			
		||||
	#define MSTATUS_FS           0x00006000 /* Floating-point Status */
 | 
			
		||||
	#define MSTATUS_FS_OFF       0x00000000
 | 
			
		||||
	#define MSTATUS_FS_INITIAL   0x00002000
 | 
			
		||||
	#define MSTATUS_FS_CLEAN     0x00004000
 | 
			
		||||
	#define MSTATUS_FS_DIRTY     0x00006000
 | 
			
		||||
 | 
			
		||||
	#if __riscv_flen == 32
 | 
			
		||||
		#define store_fpu fsw
 | 
			
		||||
		#define load_fpu flw
 | 
			
		||||
	#endif /* __riscv_flen == 32 */
 | 
			
		||||
 | 
			
		||||
	#if __riscv_flen == 64
 | 
			
		||||
		#define store_fpu fsd
 | 
			
		||||
		#define load_fpu fld
 | 
			
		||||
	#endif /* __riscv_flen == 64 */
 | 
			
		||||
 | 
			
		||||
	#define portasmFPU_CONTEXT_SIZE			(32)
 | 
			
		||||
	#define portFPUWORD_SIZE 				(__riscv_flen / 8)
 | 
			
		||||
#else
 | 
			
		||||
	#define portasmFPU_CONTEXT_SIZE			(0)
 | 
			
		||||
	#define portFPUWORD_SIZE				(0)
 | 
			
		||||
#endif /* __riscv_fdiv */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "freertos_risc_v_chip_specific_extensions.h"
 | 
			
		||||
 | 
			
		||||
@ -124,47 +85,20 @@ definitions. */
 | 
			
		||||
	#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_MTIME to either 1 (MTIME clock present) or 0 (MTIME clock not present).  See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef portHANDLE_INTERRUPT
 | 
			
		||||
	#error portHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts.
 | 
			
		||||
#ifndef portasmHANDLE_INTERRUPT
 | 
			
		||||
	#error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts.  portasmHANDLE_INTERRUPT can be defined on the assembler command line or in the appropriate freertos_risc_v_chip_specific_extensions.h header file.  https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef portHANDLE_EXCEPTION
 | 
			
		||||
	#error portHANDLE_EXCEPTION must be defined to the function to be called to handle execptions.
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
#ifndef portasmHAS_SIFIVE_CLINT
 | 
			
		||||
	#define portasmHAS_SIFIVE_CLINT 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * To maintain RISCV ABI stack alignment requirements (16bytes)
 | 
			
		||||
 * this data structure must be a MULTIPLE of 16 bytes in size.
 | 
			
		||||
 * 32 Registers (for standard core) is 16byte aligned :)
 | 
			
		||||
 * We add space to save additional information so it must be multiple of 4.
 | 
			
		||||
 * mepc 33th register 
 | 
			
		||||
 * mstatus 34th register
 | 
			
		||||
 * ruf 35th register
 | 
			
		||||
 * ruf 36th register
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PORT_CONTEXT_mepcIDX		(portasmNB_REGS_SAVED)
 | 
			
		||||
#define PORT_CONTEXT_mstatusIDX		(portasmNB_REGS_SAVED + 1)
 | 
			
		||||
 | 
			
		||||
#define portasmLAST_BASE_REGS		(portasmNB_REGS_SAVED + 4)
 | 
			
		||||
#define PORT_CONTEXT_lastIDX		((portasmNB_REGS_SAVED) + portasmADDITIONAL_CONTEXT_SIZE)
 | 
			
		||||
 | 
			
		||||
/* used in assembler, as byte offsets from the start of the context */
 | 
			
		||||
#define PORT_CONTEXT_xIDX(X)		(X) /* index into "raw" for register x? */
 | 
			
		||||
#define PORT_CONTEXT_xOFFSET(X) 	(PORT_CONTEXT_xIDX(X)		* portWORD_SIZE)
 | 
			
		||||
#define PORT_CONTEXT_mepcOFFSET     (PORT_CONTEXT_mepcIDX		* portWORD_SIZE)
 | 
			
		||||
#define PORT_CONTEXT_mstatusOFFSET  (PORT_CONTEXT_mstatusIDX	* portWORD_SIZE)
 | 
			
		||||
#define PORT_CONTEXT_rufOFFSET   	(PORT_CONTEXT_rufIDX		* portWORD_SIZE)
 | 
			
		||||
#define PORT_CONTEXT_fpuOFFSET(X) 	((X) 						* portFPUWORD_SIZE)
 | 
			
		||||
/* total size of the structure usable in ASM. */
 | 
			
		||||
 | 
			
		||||
#define portasmREGISTER_CONTEXT_WORDSIZE		((portasmLAST_BASE_REGS) * (portWORD_SIZE))
 | 
			
		||||
#define portasmADDITIONAL_CONTEXT_WORDSIZE		((portasmADDITIONAL_CONTEXT_SIZE) * (portWORD_SIZE))
 | 
			
		||||
#define portasmFPU_CONTEXT_WORDSIZE				((portasmFPU_CONTEXT_SIZE) * (portFPUWORD_SIZE))
 | 
			
		||||
/* Only the standard core registers are stored by default.  Any additional
 | 
			
		||||
registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and
 | 
			
		||||
portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
 | 
			
		||||
specific version of freertos_risc_v_chip_specific_extensions.h.  See the notes
 | 
			
		||||
at the top of this file. */
 | 
			
		||||
#define portCONTEXT_SIZE ( 30 * portWORD_SIZE )
 | 
			
		||||
 | 
			
		||||
.global xPortStartFirstTask
 | 
			
		||||
.global freertos_risc_v_trap_handler
 | 
			
		||||
@ -178,422 +112,184 @@ definitions. */
 | 
			
		||||
.extern pullNextTime
 | 
			
		||||
.extern uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
 | 
			
		||||
.extern xISRStackTop
 | 
			
		||||
.extern portHANDLE_INTERRUPT
 | 
			
		||||
.extern portHANDLE_EXCEPTION
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 
 | 
			
		||||
#ifdef __riscv_fdiv
 | 
			
		||||
.macro portSAVE_FpuReg
 | 
			
		||||
	/* get FS field from mstatus */
 | 
			
		||||
	li t0, MSTATUS_FS
 | 
			
		||||
	csrr 	t1, mstatus
 | 
			
		||||
	and t0, t1, t0
 | 
			
		||||
	li t2, MSTATUS_FS_DIRTY
 | 
			
		||||
	bne t2, t0, 1f
 | 
			
		||||
	/* FS == dirty */
 | 
			
		||||
	/* Make room for the additional FPU registers. */
 | 
			
		||||
	addi sp, sp, -portasmFPU_CONTEXT_WORDSIZE
 | 
			
		||||
	store_fpu  f0,  PORT_CONTEXT_fpuOFFSET(0)(sp)		/* f0(ft0)		FP temporary register */
 | 
			
		||||
	store_fpu  f1,  PORT_CONTEXT_fpuOFFSET(1)(sp)		/* f1(ft1)		FP temporary register */
 | 
			
		||||
	store_fpu  f2,  PORT_CONTEXT_fpuOFFSET(2)(sp)		/* f2(ft2)		FP temporary register */
 | 
			
		||||
	store_fpu  f3,  PORT_CONTEXT_fpuOFFSET(3)(sp)		/* f3(ft3)		FP temporary register */
 | 
			
		||||
	store_fpu  f4,  PORT_CONTEXT_fpuOFFSET(4)(sp)		/* f4(ft4)		FP temporary register */
 | 
			
		||||
	store_fpu  f5,  PORT_CONTEXT_fpuOFFSET(5)(sp)		/* f5(ft5)		FP temporary register */
 | 
			
		||||
	store_fpu  f6,  PORT_CONTEXT_fpuOFFSET(6)(sp)		/* f6(ft6)		FP temporary register */
 | 
			
		||||
	store_fpu  f7,  PORT_CONTEXT_fpuOFFSET(7)(sp)		/* f7(ft7)		FP temporary register */
 | 
			
		||||
.extern portasmHANDLE_INTERRUPT
 | 
			
		||||
 | 
			
		||||
	store_fpu  f8,  PORT_CONTEXT_fpuOFFSET(8)(sp)		/* f8(fs0)		FP Saved register */
 | 
			
		||||
	store_fpu  f9,  PORT_CONTEXT_fpuOFFSET(9)(sp)		/* f9(fs0)		FP Saved register */
 | 
			
		||||
 | 
			
		||||
	store_fpu  f10,  PORT_CONTEXT_fpuOFFSET(10)(sp)	/* f10(fa0)		FP arguments/return values register */
 | 
			
		||||
	store_fpu  f11,  PORT_CONTEXT_fpuOFFSET(11)(sp)	/* f11(fa1)		FP arguments/return values register */
 | 
			
		||||
 | 
			
		||||
	store_fpu  f12,  PORT_CONTEXT_fpuOFFSET(12)(sp)	/* f12(fa2)		FP arguments register */
 | 
			
		||||
	store_fpu  f13,  PORT_CONTEXT_fpuOFFSET(13)(sp)	/* f13(fa3)		FP arguments register */
 | 
			
		||||
	store_fpu  f14,  PORT_CONTEXT_fpuOFFSET(14)(sp)	/* f14(fa4)		FP arguments register */
 | 
			
		||||
	store_fpu  f15,  PORT_CONTEXT_fpuOFFSET(15)(sp)	/* f15(fa5)		FP arguments register */
 | 
			
		||||
	store_fpu  f16,  PORT_CONTEXT_fpuOFFSET(16)(sp)	/* f16(fa6)		FP arguments register */
 | 
			
		||||
	store_fpu  f17,  PORT_CONTEXT_fpuOFFSET(17)(sp)	/* f17(fa7)		FP arguments register */
 | 
			
		||||
 | 
			
		||||
	store_fpu  f18,  PORT_CONTEXT_fpuOFFSET(18)(sp)	/* f18(fs2)		FP Saved register */
 | 
			
		||||
	store_fpu  f19,  PORT_CONTEXT_fpuOFFSET(19)(sp)	/* f19(fs3)		FP Saved register */
 | 
			
		||||
	store_fpu  f20,  PORT_CONTEXT_fpuOFFSET(20)(sp)	/* f20(fs4)		FP Saved register */
 | 
			
		||||
	store_fpu  f21,  PORT_CONTEXT_fpuOFFSET(21)(sp)	/* f21(fs5)		FP Saved register */
 | 
			
		||||
	store_fpu  f22,  PORT_CONTEXT_fpuOFFSET(22)(sp)	/* f22(fs6)		FP Saved register */
 | 
			
		||||
	store_fpu  f23,  PORT_CONTEXT_fpuOFFSET(23)(sp)	/* f23(fs7)		FP Saved register */
 | 
			
		||||
	store_fpu  f24,  PORT_CONTEXT_fpuOFFSET(24)(sp)	/* f24(fs8)		FP Saved register */
 | 
			
		||||
	store_fpu  f25,  PORT_CONTEXT_fpuOFFSET(25)(sp)	/* f25(fs9)		FP Saved register */
 | 
			
		||||
	store_fpu  f26,  PORT_CONTEXT_fpuOFFSET(26)(sp)	/* f26(fs10)	FP Saved register */
 | 
			
		||||
	store_fpu  f27,  PORT_CONTEXT_fpuOFFSET(27)(sp)	/* f27(fs11)	FP Saved register */
 | 
			
		||||
 | 
			
		||||
	store_fpu  f28,  PORT_CONTEXT_fpuOFFSET(28)(sp)	/* f28(ft8)		FP temporary register */
 | 
			
		||||
	store_fpu  f29,  PORT_CONTEXT_fpuOFFSET(29)(sp)	/* f29(ft9)		FP temporary register */
 | 
			
		||||
	store_fpu  f30,  PORT_CONTEXT_fpuOFFSET(30)(sp)	/* f30(ft10)	FP temporary register */
 | 
			
		||||
	store_fpu  f31,  PORT_CONTEXT_fpuOFFSET(31)(sp)	/* f31(ft11)	FP temporary register */
 | 
			
		||||
 | 
			
		||||
	/* must set FS to clean */
 | 
			
		||||
	csrc 	mstatus, t0
 | 
			
		||||
	li 	t1, MSTATUS_FS_CLEAN
 | 
			
		||||
	csrs	mstatus, t1
 | 
			
		||||
1:
 | 
			
		||||
	.endm
 | 
			
		||||
#else
 | 
			
		||||
.macro portSAVE_FpuReg
 | 
			
		||||
	/* No fpu registers to save, so this macro does nothing. */
 | 
			
		||||
	.endm
 | 
			
		||||
#endif /* __riscv_fdiv */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#ifdef __riscv_fdiv
 | 
			
		||||
.macro portRESTORE_FpuReg
 | 
			
		||||
	/* get FS field from mstatus */
 | 
			
		||||
	li t0, MSTATUS_FS
 | 
			
		||||
	csrr 	t1, mstatus
 | 
			
		||||
	and t0, t1, t0
 | 
			
		||||
	li t2, MSTATUS_FS_OFF
 | 
			
		||||
	beq t2, t0, 1f
 | 
			
		||||
	/* FS != off */
 | 
			
		||||
	csrs mstatus, t0
 | 
			
		||||
	/* Remove space added for additional fpu registers. */
 | 
			
		||||
	addi sp, sp, portasmFPU_CONTEXT_WORDSIZE
 | 
			
		||||
	load_fpu  f0,  PORT_CONTEXT_fpuOFFSET(0)(sp)		/* f0(ft0)		FP temporary register */
 | 
			
		||||
	load_fpu  f1,  PORT_CONTEXT_fpuOFFSET(1)(sp)		/* f1(ft1)		FP temporary register */
 | 
			
		||||
	load_fpu  f2,  PORT_CONTEXT_fpuOFFSET(2)(sp)		/* f2(ft2)		FP temporary register */
 | 
			
		||||
	load_fpu  f3,  PORT_CONTEXT_fpuOFFSET(3)(sp)		/* f3(ft3)		FP temporary register */
 | 
			
		||||
	load_fpu  f4,  PORT_CONTEXT_fpuOFFSET(4)(sp)		/* f4(ft4)		FP temporary register */
 | 
			
		||||
	load_fpu  f5,  PORT_CONTEXT_fpuOFFSET(5)(sp)		/* f5(ft5)		FP temporary register */
 | 
			
		||||
	load_fpu  f6,  PORT_CONTEXT_fpuOFFSET(6)(sp)		/* f6(ft6)		FP temporary register */
 | 
			
		||||
	load_fpu  f7,  PORT_CONTEXT_fpuOFFSET(7)(sp)		/* f7(ft7)		FP temporary register */
 | 
			
		||||
 | 
			
		||||
	load_fpu  f8,  PORT_CONTEXT_fpuOFFSET(8)(sp)		/* f8(fs0)		FP Saved register */
 | 
			
		||||
	load_fpu  f9,  PORT_CONTEXT_fpuOFFSET(9)(sp)		/* f9(fs0)		FP Saved register */
 | 
			
		||||
 | 
			
		||||
	load_fpu  f10,  PORT_CONTEXT_fpuOFFSET(10)(sp)	/* f10(fa0)		FP arguments/return values register */
 | 
			
		||||
	load_fpu  f11,  PORT_CONTEXT_fpuOFFSET(11)(sp)	/* f11(fa1)		FP arguments/return values register */
 | 
			
		||||
 | 
			
		||||
	load_fpu  f12,  PORT_CONTEXT_fpuOFFSET(12)(sp)	/* f12(fa2)		FP arguments register */
 | 
			
		||||
	load_fpu  f13,  PORT_CONTEXT_fpuOFFSET(13)(sp)	/* f13(fa3)		FP arguments register */
 | 
			
		||||
	load_fpu  f14,  PORT_CONTEXT_fpuOFFSET(14)(sp)	/* f14(fa4)		FP arguments register */
 | 
			
		||||
	load_fpu  f15,  PORT_CONTEXT_fpuOFFSET(15)(sp)	/* f15(fa5)		FP arguments register */
 | 
			
		||||
	load_fpu  f16,  PORT_CONTEXT_fpuOFFSET(16)(sp)	/* f16(fa6)		FP arguments register */
 | 
			
		||||
	load_fpu  f17,  PORT_CONTEXT_fpuOFFSET(17)(sp)	/* f17(fa7)		FP arguments register */
 | 
			
		||||
 | 
			
		||||
	load_fpu  f18,  PORT_CONTEXT_fpuOFFSET(18)(sp)	/* f18(fs2)		FP Saved register */
 | 
			
		||||
	load_fpu  f19,  PORT_CONTEXT_fpuOFFSET(19)(sp)	/* f19(fs3)		FP Saved register */
 | 
			
		||||
	load_fpu  f20,  PORT_CONTEXT_fpuOFFSET(20)(sp)	/* f20(fs4)		FP Saved register */
 | 
			
		||||
	load_fpu  f21,  PORT_CONTEXT_fpuOFFSET(21)(sp)	/* f21(fs5)		FP Saved register */
 | 
			
		||||
	load_fpu  f22,  PORT_CONTEXT_fpuOFFSET(22)(sp)	/* f22(fs6)		FP Saved register */
 | 
			
		||||
	load_fpu  f23,  PORT_CONTEXT_fpuOFFSET(23)(sp)	/* f23(fs7)		FP Saved register */
 | 
			
		||||
	load_fpu  f24,  PORT_CONTEXT_fpuOFFSET(24)(sp)	/* f24(fs8)		FP Saved register */
 | 
			
		||||
	load_fpu  f25,  PORT_CONTEXT_fpuOFFSET(25)(sp)	/* f25(fs9)		FP Saved register */
 | 
			
		||||
	load_fpu  f26,  PORT_CONTEXT_fpuOFFSET(26)(sp)	/* f26(fs10)	FP Saved register */
 | 
			
		||||
	load_fpu  f27,  PORT_CONTEXT_fpuOFFSET(27)(sp)	/* f27(fs11)	FP Saved register */
 | 
			
		||||
 | 
			
		||||
	load_fpu  f28,  PORT_CONTEXT_fpuOFFSET(28)(sp)	/* f28(ft8)		FP temporary register */
 | 
			
		||||
	load_fpu  f29,  PORT_CONTEXT_fpuOFFSET(29)(sp)	/* f29(ft9)		FP temporary register */
 | 
			
		||||
	load_fpu  f30,  PORT_CONTEXT_fpuOFFSET(30)(sp)	/* f30(ft10)	FP temporary register */
 | 
			
		||||
	load_fpu  f31,  PORT_CONTEXT_fpuOFFSET(31)(sp)	/* f31(ft11)	FP temporary register */
 | 
			
		||||
 | 
			
		||||
	/* must set FS to clean */
 | 
			
		||||
	csrc 	mstatus, t0
 | 
			
		||||
	li 	t1, MSTATUS_FS_CLEAN
 | 
			
		||||
	csrs	mstatus, t1
 | 
			
		||||
1:
 | 
			
		||||
	.endm
 | 
			
		||||
#else
 | 
			
		||||
.macro portRESTORE_FpuReg
 | 
			
		||||
	/* No fpu registers to restore, so this macro does nothing. */
 | 
			
		||||
	.endm
 | 
			
		||||
#endif /* __riscv_fdiv */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.macro portSAVE_BaseReg
 | 
			
		||||
	/* Make room for the registers. */
 | 
			
		||||
	addi	sp, sp, -portasmREGISTER_CONTEXT_WORDSIZE
 | 
			
		||||
    store_x  x1,  PORT_CONTEXT_xOFFSET(1)(sp)		/* x1(ra)		Return address */
 | 
			
		||||
													/* x2(sp) ***** Should be save ouside this macro */
 | 
			
		||||
    store_x  x3,  PORT_CONTEXT_xOFFSET(3)(sp)		/* x3(gp)		Global pointer */
 | 
			
		||||
    store_x  x4,  PORT_CONTEXT_xOFFSET(4)(sp)		/* x4(tp)		Thread pointer */
 | 
			
		||||
    store_x  x5,  PORT_CONTEXT_xOFFSET(5)(sp)		/* x5(t0)		Temporary register */
 | 
			
		||||
    store_x  x6,  PORT_CONTEXT_xOFFSET(6)(sp)		/* x6(t1)		Temporary register*/
 | 
			
		||||
    store_x  x7,  PORT_CONTEXT_xOFFSET(7)(sp)		/* x7(t2)		Temporary register */
 | 
			
		||||
    store_x  x8,  PORT_CONTEXT_xOFFSET(8)(sp)		/* x8(s0/fp)	Saved register/Frame pointer */
 | 
			
		||||
    store_x  x9,  PORT_CONTEXT_xOFFSET(9)(sp)		/* x9(s1)		Saved register */
 | 
			
		||||
    store_x  x10, PORT_CONTEXT_xOFFSET(10)(sp)		/* x10(a0)		Function argument */
 | 
			
		||||
    store_x  x11, PORT_CONTEXT_xOFFSET(11)(sp)		/* x11(a1)		Function argument */
 | 
			
		||||
    store_x  x12, PORT_CONTEXT_xOFFSET(12)(sp)		/* x12(a2)		Function argument */
 | 
			
		||||
    store_x  x13, PORT_CONTEXT_xOFFSET(13)(sp)		/* x13(a3)		Function argument */
 | 
			
		||||
    store_x  x14, PORT_CONTEXT_xOFFSET(14)(sp)		/* x14(a4)		Function argument */
 | 
			
		||||
    store_x  x15, PORT_CONTEXT_xOFFSET(15)(sp)		/* x15(a5)		Function argument */
 | 
			
		||||
#ifndef __riscv_32e
 | 
			
		||||
    store_x  x16, PORT_CONTEXT_xOFFSET(16)(sp)		/* x16(a6)		Function arguments */
 | 
			
		||||
    store_x  x17, PORT_CONTEXT_xOFFSET(17)(sp)		/* x17(a7)		Function arguments */
 | 
			
		||||
    store_x  x18, PORT_CONTEXT_xOFFSET(18)(sp)		/* x18(s2)		Saved register */
 | 
			
		||||
    store_x  x19, PORT_CONTEXT_xOFFSET(19)(sp)		/* x19(s3)		Saved register */
 | 
			
		||||
    store_x  x20, PORT_CONTEXT_xOFFSET(20)(sp)		/* x20(s4)		Saved register */
 | 
			
		||||
    store_x  x21, PORT_CONTEXT_xOFFSET(21)(sp)		/* x21(s5)		Saved register */
 | 
			
		||||
    store_x  x22, PORT_CONTEXT_xOFFSET(22)(sp)		/* x22(s6)		Saved register */
 | 
			
		||||
    store_x  x23, PORT_CONTEXT_xOFFSET(23)(sp)		/* x23(s7)		Saved register */
 | 
			
		||||
    store_x  x24, PORT_CONTEXT_xOFFSET(24)(sp)		/* x24(s8)		Saved register */
 | 
			
		||||
    store_x  x25, PORT_CONTEXT_xOFFSET(25)(sp)		/* x25(s9)		Saved register */
 | 
			
		||||
    store_x  x26, PORT_CONTEXT_xOFFSET(26)(sp)		/* x26(s10)		Saved register */
 | 
			
		||||
    store_x  x27, PORT_CONTEXT_xOFFSET(27)(sp)		/* x27(s11)		Saved register */
 | 
			
		||||
    store_x  x28, PORT_CONTEXT_xOFFSET(28)(sp)		/* x28(t3)		Temporary register */
 | 
			
		||||
    store_x  x29, PORT_CONTEXT_xOFFSET(29)(sp)		/* x29(t4)		Temporary register */
 | 
			
		||||
    store_x  x30, PORT_CONTEXT_xOFFSET(30)(sp)		/* x30(t5)		Temporary register */
 | 
			
		||||
    store_x  x31, PORT_CONTEXT_xOFFSET(31)(sp)		/* x31(t6)		Temporary register */
 | 
			
		||||
#endif /* __riscv_32e */
 | 
			
		||||
	/* Save mcause, mepc & mstatus state */
 | 
			
		||||
	csrr a4, mepc
 | 
			
		||||
	csrr a5, mstatus		/* Required for MPIE bit. */
 | 
			
		||||
	store_x a4, PORT_CONTEXT_mepcOFFSET(sp)
 | 
			
		||||
	store_x a5, PORT_CONTEXT_mstatusOFFSET(sp)
 | 
			
		||||
	.endm
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.macro portRESTORE_BaseReg
 | 
			
		||||
	/* Restore mepc & mstatus state */
 | 
			
		||||
	load_x  t0, PORT_CONTEXT_mepcOFFSET(sp)
 | 
			
		||||
	load_x  t1, PORT_CONTEXT_mstatusOFFSET(sp)
 | 
			
		||||
	csrw	mepc, t0
 | 
			
		||||
	csrw	mstatus, t1
 | 
			
		||||
 | 
			
		||||
    load_x  x1,  PORT_CONTEXT_xOFFSET(1)(sp)		/* x1(ra)		Return address */
 | 
			
		||||
													/* x2(sp) ***** Should be save ouside this macro */
 | 
			
		||||
    load_x  x3,  PORT_CONTEXT_xOFFSET(3)(sp)		/* x3(gp)		Global pointer */
 | 
			
		||||
    load_x  x4,  PORT_CONTEXT_xOFFSET(4)(sp)		/* x4(tp)		Thread pointer */
 | 
			
		||||
    load_x  x5,  PORT_CONTEXT_xOFFSET(5)(sp)		/* x5(t0)		Temporary register */
 | 
			
		||||
    load_x  x6,  PORT_CONTEXT_xOFFSET(6)(sp)		/* x6(t1)		Temporary register*/
 | 
			
		||||
    load_x  x7,  PORT_CONTEXT_xOFFSET(7)(sp)		/* x7(t2)		Temporary register */
 | 
			
		||||
    load_x  x8,  PORT_CONTEXT_xOFFSET(8)(sp)		/* x8(s0/fp)	Saved register/Frame pointer */
 | 
			
		||||
    load_x  x9,  PORT_CONTEXT_xOFFSET(9)(sp)		/* x9(s1)		Saved register */
 | 
			
		||||
    load_x  x10, PORT_CONTEXT_xOFFSET(10)(sp)		/* x10(a0)		Function argument */
 | 
			
		||||
    load_x  x11, PORT_CONTEXT_xOFFSET(11)(sp)		/* x11(a1)		Function argument */
 | 
			
		||||
    load_x  x12, PORT_CONTEXT_xOFFSET(12)(sp)		/* x12(a2)		Function argument */
 | 
			
		||||
    load_x  x13, PORT_CONTEXT_xOFFSET(13)(sp)		/* x13(a3)		Function argument */
 | 
			
		||||
    load_x  x14, PORT_CONTEXT_xOFFSET(14)(sp)		/* x14(a4)		Function argument */
 | 
			
		||||
    load_x  x15, PORT_CONTEXT_xOFFSET(15)(sp)		/* x15(a5)		Function argument */
 | 
			
		||||
#ifndef __riscv_32e
 | 
			
		||||
    load_x  x16, PORT_CONTEXT_xOFFSET(16)(sp)		/* x16(a6)		Function arguments */
 | 
			
		||||
    load_x  x17, PORT_CONTEXT_xOFFSET(17)(sp)		/* x17(a7)		Function arguments */
 | 
			
		||||
    load_x  x18, PORT_CONTEXT_xOFFSET(18)(sp)		/* x18(s2)		Saved register */
 | 
			
		||||
    load_x  x19, PORT_CONTEXT_xOFFSET(19)(sp)		/* x19(s3)		Saved register */
 | 
			
		||||
    load_x  x20, PORT_CONTEXT_xOFFSET(20)(sp)		/* x20(s4)		Saved register */
 | 
			
		||||
    load_x  x21, PORT_CONTEXT_xOFFSET(21)(sp)		/* x21(s5)		Saved register */
 | 
			
		||||
    load_x  x22, PORT_CONTEXT_xOFFSET(22)(sp)		/* x22(s6)		Saved register */
 | 
			
		||||
    load_x  x23, PORT_CONTEXT_xOFFSET(23)(sp)		/* x23(s7)		Saved register */
 | 
			
		||||
    load_x  x24, PORT_CONTEXT_xOFFSET(24)(sp)		/* x24(s8)		Saved register */
 | 
			
		||||
    load_x  x25, PORT_CONTEXT_xOFFSET(25)(sp)		/* x25(s9)		Saved register */
 | 
			
		||||
    load_x  x26, PORT_CONTEXT_xOFFSET(26)(sp)		/* x26(s10)		Saved register */
 | 
			
		||||
    load_x  x27, PORT_CONTEXT_xOFFSET(27)(sp)		/* x27(s11)		Saved register */
 | 
			
		||||
    load_x  x28, PORT_CONTEXT_xOFFSET(28)(sp)		/* x28(t3)		Temporary register */
 | 
			
		||||
    load_x  x29, PORT_CONTEXT_xOFFSET(29)(sp)		/* x29(t4)		Temporary register */
 | 
			
		||||
    load_x  x30, PORT_CONTEXT_xOFFSET(30)(sp)		/* x30(t5)		Temporary register */
 | 
			
		||||
    load_x  x31, PORT_CONTEXT_xOFFSET(31)(sp)		/* x31(t6)		Temporary register */
 | 
			
		||||
#endif /* __riscv_32e */
 | 
			
		||||
	.endm
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.align 8
 | 
			
		||||
.func
 | 
			
		||||
freertos_risc_v_trap_handler:
 | 
			
		||||
	/* We do not know if this is an ASYNC or SYNC
 | 
			
		||||
	 * If ASYNC, it is a normal interrupt
 | 
			
		||||
	 *  and the stack pointer is assumed good.
 | 
			
		||||
	 * else (SYNC)
 | 
			
		||||
	 *  We could be here due to a bus fault.
 | 
			
		||||
	 */
 | 
			
		||||
    csrw	mscratch, t0
 | 
			
		||||
    csrr	t0, mcause
 | 
			
		||||
    blt  	t0, x0, handle_interrupt
 | 
			
		||||
	addi sp, sp, -portCONTEXT_SIZE
 | 
			
		||||
	store_x x1, 1 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x5, 2 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x6, 3 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x7, 4 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x8, 5 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x9, 6 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x10, 7 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x11, 8 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x12, 9 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x13, 10 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x14, 11 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x15, 12 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x16, 13 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x17, 14 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x18, 15 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x19, 16 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x20, 17 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x21, 18 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x22, 19 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x23, 20 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x24, 21 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x25, 22 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x26, 23 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x27, 24 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x28, 25 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x29, 26 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x30, 27 * portWORD_SIZE( sp )
 | 
			
		||||
	store_x x31, 28 * portWORD_SIZE( sp )
 | 
			
		||||
 | 
			
		||||
handle_exception:
 | 
			
		||||
	/* mscratch = old t0
 | 
			
		||||
	 * t0 = mcause
 | 
			
		||||
	 * mcause = small number 0..16
 | 
			
		||||
	 *  0 Instruction address misaligned
 | 
			
		||||
	 *  1 Instruction access fault
 | 
			
		||||
	 *  2 Illegal instruction
 | 
			
		||||
	 *  3 Breakpoint
 | 
			
		||||
	 *  4 Load address misaligned
 | 
			
		||||
	 *  5 Load access fault
 | 
			
		||||
	 *  6 Store/AMO address misaligned
 | 
			
		||||
	 *  7 Store/AMO access fault
 | 
			
		||||
	 *  8 Environment call from U-mode
 | 
			
		||||
	 *  9 Environment call from S-mode
 | 
			
		||||
	 *  10 Reserved
 | 
			
		||||
	 *  11 Environment call from M-mode
 | 
			
		||||
	 *  12 Instruction page fault
 | 
			
		||||
	 *  13 Load page fault
 | 
			
		||||
	 *  14 Reserved
 | 
			
		||||
	 *  15 Store/AMO page fault
 | 
			
		||||
	 *  ≥16 Reserved
 | 
			
		||||
	 *
 | 
			
		||||
	 * if( mcause between 8 and 11  ) we are good - ecall
 | 
			
		||||
	 * else: problem
 | 
			
		||||
	 */
 | 
			
		||||
	csrr t0, mstatus					/* Required for MPIE bit. */
 | 
			
		||||
	store_x t0, 29 * portWORD_SIZE( sp )
 | 
			
		||||
 | 
			
		||||
	addi	t0, t0, -8
 | 
			
		||||
	blt		t0, x0, is_exception /* mcause < 8, must be fault */
 | 
			
		||||
	addi	t0, t0, -4
 | 
			
		||||
	blt		t0, x0, ecall_yield
 | 
			
		||||
	portasmSAVE_ADDITIONAL_REGISTERS	/* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
 | 
			
		||||
 | 
			
		||||
is_exception:
 | 
			
		||||
	/* restore t0 and save sp in mscratch. */
 | 
			
		||||
	csrr	t0, mscratch
 | 
			
		||||
	   csrw	mscratch, sp
 | 
			
		||||
	/* Switch to ISR stack before function call. */
 | 
			
		||||
	load_x	sp, xISRStackTop			
 | 
			
		||||
	portSAVE_BaseReg
 | 
			
		||||
	csrrw	t0, mscratch, t0
 | 
			
		||||
	/* SP = X2, so save it */
 | 
			
		||||
	store_x	t0, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	/* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
 | 
			
		||||
	portasmSAVE_ADDITIONAL_REGISTERS
 | 
			
		||||
	/* Save any fpu registers */
 | 
			
		||||
	portSAVE_FpuReg
 | 
			
		||||
	/* Execption is treated by external function */
 | 
			
		||||
	jal portHANDLE_EXCEPTION
 | 
			
		||||
	/* in case that the go back from exception, restore registers */
 | 
			
		||||
	portRESTORE_FpuReg
 | 
			
		||||
	portasmRESTORE_ADDITIONAL_REGISTERS
 | 
			
		||||
	portRESTORE_BaseReg
 | 
			
		||||
	load_x  x2, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	mret
 | 
			
		||||
 
 | 
			
		||||
ecall_yield:
 | 
			
		||||
	portSAVE_BaseReg
 | 
			
		||||
	/* a4 = mepc
 | 
			
		||||
	 * a5 = mstatus
 | 
			
		||||
	 * s0 will be use for pxCurrentTCB
 | 
			
		||||
	 * s1 will be use to save sp
 | 
			
		||||
	 */
 | 
			
		||||
	/* Synchronous so updated exception return address to the instruction after the instruction that generated the exeption. */
 | 
			
		||||
	addi	t0, a4, 4
 | 
			
		||||
	store_x	t0, PORT_CONTEXT_mepcOFFSET(sp) 
 | 
			
		||||
	/* Store the value of sp when the interrupt occur */
 | 
			
		||||
	addi 	t0, sp, portasmREGISTER_CONTEXT_WORDSIZE
 | 
			
		||||
	store_x t0, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	load_x  t0, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	store_x  sp, 0( t0 )				/* Write sp to first TCB member. */
 | 
			
		||||
 | 
			
		||||
	/* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
 | 
			
		||||
	portasmSAVE_ADDITIONAL_REGISTERS
 | 
			
		||||
	/* Save any fpu registers */
 | 
			
		||||
	portSAVE_FpuReg
 | 
			
		||||
	csrr a0, mcause
 | 
			
		||||
	csrr a1, mepc
 | 
			
		||||
 | 
			
		||||
	/* Load pxCurrentTCB and update first TCB member(pxTopOfStack) with sp. */
 | 
			
		||||
	load_x  s0, pxCurrentTCB
 | 
			
		||||
	store_x  sp, 0( s0 )
 | 
			
		||||
test_if_asynchronous:
 | 
			
		||||
	srli a2, a0, __riscv_xlen - 1		/* MSB of mcause is 1 if handing an asynchronous interrupt - shift to LSB to clear other bits. */
 | 
			
		||||
	beq a2, x0, handle_synchronous		/* Branch past interrupt handing if not asynchronous. */
 | 
			
		||||
	store_x a1, 0( sp )					/* Asynch so save unmodified exception return address. */
 | 
			
		||||
 | 
			
		||||
	/* Save sp into s1 */
 | 
			
		||||
	mv  s1, sp
 | 
			
		||||
	load_x sp, xISRStackTop			/* Switch to ISR stack before function call. */
 | 
			
		||||
 | 
			
		||||
	j	switch_context
 | 
			
		||||
 | 
			
		||||
handle_interrupt:
 | 
			
		||||
	portSAVE_BaseReg
 | 
			
		||||
	/* a4 = mepc
 | 
			
		||||
	 * a5 = mstatus
 | 
			
		||||
	 * s0 will be use for pxCurrentTCB
 | 
			
		||||
	 * s1 will be use to save sp
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* Store the value of sp when the interrupt occur */
 | 
			
		||||
	addi t0, sp, portasmREGISTER_CONTEXT_WORDSIZE
 | 
			
		||||
	store_x  t0, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
 | 
			
		||||
	/* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
 | 
			
		||||
	portasmSAVE_ADDITIONAL_REGISTERS
 | 
			
		||||
	/* Save any fpu registers */
 | 
			
		||||
	portSAVE_FpuReg
 | 
			
		||||
 | 
			
		||||
	/* Load pxCurrentTCB and update first TCB member(pxTopOfStack) with sp. */
 | 
			
		||||
	load_x  s0, pxCurrentTCB
 | 
			
		||||
	store_x  sp, 0( s0 )
 | 
			
		||||
 | 
			
		||||
	/* Save sp into s1 */
 | 
			
		||||
	mv  s1, sp
 | 
			
		||||
	load_x sp, xISRStackTop			/* Switch to ISR stack before function call. */
 | 
			
		||||
handle_asynchronous:
 | 
			
		||||
 | 
			
		||||
#if( portasmHAS_MTIME != 0 )
 | 
			
		||||
	addi t0, x0, 1
 | 
			
		||||
 | 
			
		||||
	slli t0, t0, __riscv_xlen - 1   /* LSB is already set, shift into MSB.  Shift 31 on 32-bit or 63 on 64-bit cores. */
 | 
			
		||||
	addi t1, t0, 7					/* 0x8000[]0007 == machine timer interrupt. */
 | 
			
		||||
    csrr t2, mcause
 | 
			
		||||
	bne t2, t1, test_if_external_interrupt
 | 
			
		||||
	test_if_mtimer:						/* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
 | 
			
		||||
 | 
			
		||||
	load_x t0, pullMachineTimerCompareRegister  /* Load address of compare register into t0. */
 | 
			
		||||
	load_x t1, pullNextTime  		/* Load the address of ullNextTime into t1. */
 | 
			
		||||
		addi t0, x0, 1
 | 
			
		||||
 | 
			
		||||
	#if( __riscv_xlen == 32 )
 | 
			
		||||
		/* Update the 64-bit mtimer compare match value in two 32-bit writes. */
 | 
			
		||||
		lw 	a0, 0(t1)				/* Load the low word of ullNextTime into a0. */
 | 
			
		||||
		lw 	a1, 4(t1)				/* Load the high word of ullNextTime into a1. */
 | 
			
		||||
		li  t2, -1
 | 
			
		||||
		sw 	t2, 4(t0)				/* Store low word of ullNextTime into compare register. */
 | 
			
		||||
		sw 	a0, 0(t0)				/* Store low word of ullNextTime into compare register. */
 | 
			
		||||
		sw 	a1, 4(t0)				/* Store high word of ullNextTime into compare register. */
 | 
			
		||||
		lw 	t0, uxTimerIncrementsForOneTick	/* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
 | 
			
		||||
		add a2, t0, a0				/* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
 | 
			
		||||
		sltu t2, a2, a0				/* See if the sum of low words overflowed (what about the zero case?). */
 | 
			
		||||
		add a3, a1, t2				/* Add overflow to high word of ullNextTime. */
 | 
			
		||||
		sw 	a2, 0(t1)				/* Store new low word of ullNextTime. */
 | 
			
		||||
		sw 	a3, 4(t1)				/* Store new high word of ullNextTime. */
 | 
			
		||||
	#endif /* ( __riscv_xlen == 32 ) */
 | 
			
		||||
	#if( __riscv_xlen == 64 )
 | 
			
		||||
		/* Update the 64-bit mtimer compare match value. */
 | 
			
		||||
		ld 	a0, 0(t1)			 	/* Load ullNextTime into a0. */
 | 
			
		||||
		sd 	a0, 0(t0)				/* Store ullNextTime into compare register. */
 | 
			
		||||
		ld 	t0, uxTimerIncrementsForOneTick  /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
 | 
			
		||||
		add 	a2, t0, a0				/* Add ullNextTime to the timer increments for one tick. */
 | 
			
		||||
		sd 	a2, 0(t1)				/* Store ullNextTime. */
 | 
			
		||||
	#endif /* ( __riscv_xlen == 64 ) */
 | 
			
		||||
		slli t0, t0, __riscv_xlen - 1   /* LSB is already set, shift into MSB.  Shift 31 on 32-bit or 63 on 64-bit cores. */
 | 
			
		||||
		addi t1, t0, 7					/* 0x8000[]0007 == machine timer interrupt. */
 | 
			
		||||
		bne a0, t1, test_if_external_interrupt
 | 
			
		||||
 | 
			
		||||
	jal xTaskIncrementTick
 | 
			
		||||
	beqz a0, restore_before_exit		/* Don't switch context if incrementing tick didn't unblock a task. */
 | 
			
		||||
	j switch_context
 | 
			
		||||
		load_x t0, pullMachineTimerCompareRegister  /* Load address of compare register into t0. */
 | 
			
		||||
		load_x t1, pullNextTime  		/* Load the address of ullNextTime into t1. */
 | 
			
		||||
 | 
			
		||||
restore_before_exit:
 | 
			
		||||
	mv  sp, s1
 | 
			
		||||
	j end_trap_handler
 | 
			
		||||
		#if( __riscv_xlen == 32 )
 | 
			
		||||
 | 
			
		||||
test_if_external_interrupt:			/* If there is a CLINT and the mtimer interrupt is not pending then check to see if an external interrupt is pending. */
 | 
			
		||||
	addi t1, t1, 4					/* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
 | 
			
		||||
    csrr t2, mcause
 | 
			
		||||
	bne t2, t1, unrecoverable_error	/* Something as yet unhandled. */
 | 
			
		||||
	j unrecoverable_error
 | 
			
		||||
#endif /* ( portasmHAS_MTIME != 0 ) */
 | 
			
		||||
			/* Update the 64-bit mtimer compare match value in two 32-bit writes. */
 | 
			
		||||
			li t4, -1
 | 
			
		||||
			lw t2, 0(t1)				/* Load the low word of ullNextTime into t2. */
 | 
			
		||||
			lw t3, 4(t1)				/* Load the high word of ullNextTime into t3. */
 | 
			
		||||
			sw t4, 0(t0)				/* Low word no smaller than old value to start with - will be overwritten below. */
 | 
			
		||||
			sw t3, 4(t0)				/* Store high word of ullNextTime into compare register.  No smaller than new value. */
 | 
			
		||||
			sw t2, 0(t0)				/* Store low word of ullNextTime into compare register. */
 | 
			
		||||
			lw t0, uxTimerIncrementsForOneTick	/* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
 | 
			
		||||
			add t4, t0, t2				/* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
 | 
			
		||||
			sltu t5, t4, t2				/* See if the sum of low words overflowed (what about the zero case?). */
 | 
			
		||||
			add t6, t3, t5				/* Add overflow to high word of ullNextTime. */
 | 
			
		||||
			sw t4, 0(t1)				/* Store new low word of ullNextTime. */
 | 
			
		||||
			sw t6, 4(t1)				/* Store new high word of ullNextTime. */
 | 
			
		||||
 | 
			
		||||
external_interrupt:
 | 
			
		||||
	/* Switch to ISR stack before function call. */
 | 
			
		||||
	load_x sp, xISRStackTop
 | 
			
		||||
	jal portHANDLE_INTERRUPT
 | 
			
		||||
	mv	sp, s1
 | 
			
		||||
	j end_trap_handler
 | 
			
		||||
		#endif /* __riscv_xlen == 32 */
 | 
			
		||||
 | 
			
		||||
unrecoverable_error:
 | 
			
		||||
    csrr 	t0, mcause              /* For viewing in the debugger only. */
 | 
			
		||||
    csrr	t1, mepc                /* For viewing in the debugger only. */
 | 
			
		||||
    csrr 	t2, mstatus
 | 
			
		||||
	wfi
 | 
			
		||||
	j unrecoverable_error
 | 
			
		||||
		#if( __riscv_xlen == 64 )
 | 
			
		||||
 | 
			
		||||
switch_context:
 | 
			
		||||
	jal	vTaskSwitchContext
 | 
			
		||||
	load_x s0, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	load_x  sp, 0( s0 )				/* Read sp from first TCB member. */
 | 
			
		||||
			/* Update the 64-bit mtimer compare match value. */
 | 
			
		||||
			ld t2, 0(t1)			 	/* Load ullNextTime into t2. */
 | 
			
		||||
			sd t2, 0(t0)				/* Store ullNextTime into compare register. */
 | 
			
		||||
			ld t0, uxTimerIncrementsForOneTick  /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
 | 
			
		||||
			add t4, t0, t2				/* Add ullNextTime to the timer increments for one tick. */
 | 
			
		||||
			sd t4, 0(t1)				/* Store ullNextTime. */
 | 
			
		||||
 | 
			
		||||
end_trap_handler:	
 | 
			
		||||
	load_x s0, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	load_x  t1, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	store_x  t1, 0( s0 )			/* Write sp saved value to first TCB member. */
 | 
			
		||||
		#endif /* __riscv_xlen == 64 */
 | 
			
		||||
 | 
			
		||||
		load_x sp, xISRStackTop			/* Switch to ISR stack before function call. */
 | 
			
		||||
		jal xTaskIncrementTick
 | 
			
		||||
		beqz a0, processed_source		/* Don't switch context if incrementing tick didn't unblock a task. */
 | 
			
		||||
		jal vTaskSwitchContext
 | 
			
		||||
		j processed_source
 | 
			
		||||
 | 
			
		||||
	test_if_external_interrupt:			/* If there is a CLINT and the mtimer interrupt is not pending then check to see if an external interrupt is pending. */
 | 
			
		||||
		addi t1, t1, 4					/* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
 | 
			
		||||
		bne a0, t1, as_yet_unhandled	/* Something as yet unhandled. */
 | 
			
		||||
 | 
			
		||||
#endif /* portasmHAS_MTIME */
 | 
			
		||||
 | 
			
		||||
	load_x sp, xISRStackTop				/* Switch to ISR stack before function call. */
 | 
			
		||||
	jal portasmHANDLE_INTERRUPT			/* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
 | 
			
		||||
	j processed_source
 | 
			
		||||
 | 
			
		||||
handle_synchronous:
 | 
			
		||||
	addi a1, a1, 4						/* Synchronous so updated exception return address to the instruction after the instruction that generated the exeption. */
 | 
			
		||||
	store_x a1, 0( sp )					/* Save updated exception return address. */
 | 
			
		||||
 | 
			
		||||
test_if_environment_call:
 | 
			
		||||
	li t0, 11 							/* 11 == environment call. */
 | 
			
		||||
	bne a0, t0, is_exception			/* Not an M environment call, so some other exception. */
 | 
			
		||||
	load_x sp, xISRStackTop				/* Switch to ISR stack before function call. */
 | 
			
		||||
	jal vTaskSwitchContext
 | 
			
		||||
	j processed_source
 | 
			
		||||
 | 
			
		||||
is_exception:
 | 
			
		||||
	csrr t0, mcause						/* For viewing in the debugger only. */
 | 
			
		||||
	csrr t1, mepc						/* For viewing in the debugger only */
 | 
			
		||||
	csrr t2, mstatus
 | 
			
		||||
	j is_exception						/* No other exceptions handled yet. */
 | 
			
		||||
 | 
			
		||||
as_yet_unhandled:
 | 
			
		||||
	csrr t0, mcause						/* For viewing in the debugger only. */
 | 
			
		||||
	j as_yet_unhandled
 | 
			
		||||
 | 
			
		||||
processed_source:
 | 
			
		||||
	load_x  t1, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	load_x  sp, 0( t1 )				 	/* Read sp from first TCB member. */
 | 
			
		||||
 | 
			
		||||
	/* Load mret with the address of the next instruction in the task to run next. */
 | 
			
		||||
	load_x t0, 0( sp )
 | 
			
		||||
	csrw mepc, t0
 | 
			
		||||
 | 
			
		||||
	portasmRESTORE_ADDITIONAL_REGISTERS	/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
 | 
			
		||||
 | 
			
		||||
	/* Load mstatus with the interrupt enable bits used by the task. */
 | 
			
		||||
	load_x  t0, 29 * portWORD_SIZE( sp )
 | 
			
		||||
	csrw mstatus, t0						/* Required for MPIE bit. */
 | 
			
		||||
 | 
			
		||||
	load_x  x1, 1 * portWORD_SIZE( sp )
 | 
			
		||||
	load_x  x5, 2 * portWORD_SIZE( sp )		/* t0 */
 | 
			
		||||
	load_x  x6, 3 * portWORD_SIZE( sp )		/* t1 */
 | 
			
		||||
	load_x  x7, 4 * portWORD_SIZE( sp )		/* t2 */
 | 
			
		||||
	load_x  x8, 5 * portWORD_SIZE( sp )		/* s0/fp */
 | 
			
		||||
	load_x  x9, 6 * portWORD_SIZE( sp )		/* s1 */
 | 
			
		||||
	load_x  x10, 7 * portWORD_SIZE( sp )	/* a0 */
 | 
			
		||||
	load_x  x11, 8 * portWORD_SIZE( sp )	/* a1 */
 | 
			
		||||
	load_x  x12, 9 * portWORD_SIZE( sp )	/* a2 */
 | 
			
		||||
	load_x  x13, 10 * portWORD_SIZE( sp )	/* a3 */
 | 
			
		||||
	load_x  x14, 11 * portWORD_SIZE( sp )	/* a4 */
 | 
			
		||||
	load_x  x15, 12 * portWORD_SIZE( sp )	/* a5 */
 | 
			
		||||
	load_x  x16, 13 * portWORD_SIZE( sp )	/* a6 */
 | 
			
		||||
	load_x  x17, 14 * portWORD_SIZE( sp )	/* a7 */
 | 
			
		||||
	load_x  x18, 15 * portWORD_SIZE( sp )	/* s2 */
 | 
			
		||||
	load_x  x19, 16 * portWORD_SIZE( sp )	/* s3 */
 | 
			
		||||
	load_x  x20, 17 * portWORD_SIZE( sp )	/* s4 */
 | 
			
		||||
	load_x  x21, 18 * portWORD_SIZE( sp )	/* s5 */
 | 
			
		||||
	load_x  x22, 19 * portWORD_SIZE( sp )	/* s6 */
 | 
			
		||||
	load_x  x23, 20 * portWORD_SIZE( sp )	/* s7 */
 | 
			
		||||
	load_x  x24, 21 * portWORD_SIZE( sp )	/* s8 */
 | 
			
		||||
	load_x  x25, 22 * portWORD_SIZE( sp )	/* s9 */
 | 
			
		||||
	load_x  x26, 23 * portWORD_SIZE( sp )	/* s10 */
 | 
			
		||||
	load_x  x27, 24 * portWORD_SIZE( sp )	/* s11 */
 | 
			
		||||
	load_x  x28, 25 * portWORD_SIZE( sp )	/* t3 */
 | 
			
		||||
	load_x  x29, 26 * portWORD_SIZE( sp )	/* t4 */
 | 
			
		||||
	load_x  x30, 27 * portWORD_SIZE( sp )	/* t5 */
 | 
			
		||||
	load_x  x31, 28 * portWORD_SIZE( sp )	/* t6 */
 | 
			
		||||
	addi sp, sp, portCONTEXT_SIZE
 | 
			
		||||
 | 
			
		||||
	/* restore registers */
 | 
			
		||||
	portRESTORE_FpuReg
 | 
			
		||||
	portasmRESTORE_ADDITIONAL_REGISTERS
 | 
			
		||||
	portRESTORE_BaseReg
 | 
			
		||||
	load_x  x2, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	mret
 | 
			
		||||
	.endfunc
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -608,37 +304,49 @@ xPortStartFirstTask:
 | 
			
		||||
	outside of this file. */
 | 
			
		||||
	la t0, freertos_risc_v_trap_handler
 | 
			
		||||
	csrw mtvec, t0
 | 
			
		||||
#endif /* ( portasmHAS_SIFIVE_CLINT != 0 ) */
 | 
			
		||||
#endif /* portasmHAS_CLILNT */
 | 
			
		||||
 | 
			
		||||
	/** Set all register to the FirstTask context */
 | 
			
		||||
	load_x  t2, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	load_x  sp, 0( t2 )				 	/* Read sp from first TCB member. */
 | 
			
		||||
	load_x  sp, pxCurrentTCB			/* Load pxCurrentTCB. */
 | 
			
		||||
	load_x  sp, 0( sp )				 	/* Read sp from first TCB member. */
 | 
			
		||||
 | 
			
		||||
	/* Restore first TCB member */
 | 
			
		||||
	load_x  t1,  PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	store_x  t1, 0( t2 )				/* Write sp saved value to first TCB member. */
 | 
			
		||||
	load_x  x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
 | 
			
		||||
 | 
			
		||||
	/* enable interrupt */
 | 
			
		||||
    #if( portasmHAS_MTIME != 0 )
 | 
			
		||||
	    li t0, 0x880
 | 
			
		||||
	    csrs mie, t0
 | 
			
		||||
    #else
 | 
			
		||||
	    li t0, 0x800
 | 
			
		||||
	    csrs mie, t0
 | 
			
		||||
    #endif /* ( portasmHAS_MTIME != 0 ) */
 | 
			
		||||
	portasmRESTORE_ADDITIONAL_REGISTERS	/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
 | 
			
		||||
 | 
			
		||||
	portRESTORE_FpuReg
 | 
			
		||||
	portasmRESTORE_ADDITIONAL_REGISTERS
 | 
			
		||||
	/* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
 | 
			
		||||
	load_x  t1, PORT_CONTEXT_mstatusOFFSET(sp)
 | 
			
		||||
	addi	t1, t1, 0x08				
 | 
			
		||||
	store_x t1, PORT_CONTEXT_mstatusOFFSET(sp)
 | 
			
		||||
	load_x  x6, 3 * portWORD_SIZE( sp )		/* t1 */
 | 
			
		||||
	load_x  x7, 4 * portWORD_SIZE( sp )		/* t2 */
 | 
			
		||||
	load_x  x8, 5 * portWORD_SIZE( sp )		/* s0/fp */
 | 
			
		||||
	load_x  x9, 6 * portWORD_SIZE( sp )		/* s1 */
 | 
			
		||||
	load_x  x10, 7 * portWORD_SIZE( sp )	/* a0 */
 | 
			
		||||
	load_x  x11, 8 * portWORD_SIZE( sp )	/* a1 */
 | 
			
		||||
	load_x  x12, 9 * portWORD_SIZE( sp )	/* a2 */
 | 
			
		||||
	load_x  x13, 10 * portWORD_SIZE( sp )	/* a3 */
 | 
			
		||||
	load_x  x14, 11 * portWORD_SIZE( sp )	/* a4 */
 | 
			
		||||
	load_x  x15, 12 * portWORD_SIZE( sp )	/* a5 */
 | 
			
		||||
	load_x  x16, 13 * portWORD_SIZE( sp )	/* a6 */
 | 
			
		||||
	load_x  x17, 14 * portWORD_SIZE( sp )	/* a7 */
 | 
			
		||||
	load_x  x18, 15 * portWORD_SIZE( sp )	/* s2 */
 | 
			
		||||
	load_x  x19, 16 * portWORD_SIZE( sp )	/* s3 */
 | 
			
		||||
	load_x  x20, 17 * portWORD_SIZE( sp )	/* s4 */
 | 
			
		||||
	load_x  x21, 18 * portWORD_SIZE( sp )	/* s5 */
 | 
			
		||||
	load_x  x22, 19 * portWORD_SIZE( sp )	/* s6 */
 | 
			
		||||
	load_x  x23, 20 * portWORD_SIZE( sp )	/* s7 */
 | 
			
		||||
	load_x  x24, 21 * portWORD_SIZE( sp )	/* s8 */
 | 
			
		||||
	load_x  x25, 22 * portWORD_SIZE( sp )	/* s9 */
 | 
			
		||||
	load_x  x26, 23 * portWORD_SIZE( sp )	/* s10 */
 | 
			
		||||
	load_x  x27, 24 * portWORD_SIZE( sp )	/* s11 */
 | 
			
		||||
	load_x  x28, 25 * portWORD_SIZE( sp )	/* t3 */
 | 
			
		||||
	load_x  x29, 26 * portWORD_SIZE( sp )	/* t4 */
 | 
			
		||||
	load_x  x30, 27 * portWORD_SIZE( sp )	/* t5 */
 | 
			
		||||
	load_x  x31, 28 * portWORD_SIZE( sp )	/* t6 */
 | 
			
		||||
 | 
			
		||||
	portRESTORE_BaseReg
 | 
			
		||||
	load_x  x5, 29 * portWORD_SIZE( sp )	/* Initial mstatus into x5 (t0) */
 | 
			
		||||
	addi x5, x5, 0x08						/* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
 | 
			
		||||
	csrrw  x0, mstatus, x5					/* Interrupts enabled from here! */
 | 
			
		||||
	load_x  x5, 2 * portWORD_SIZE( sp )		/* Initial x5 (t0) value. */
 | 
			
		||||
 | 
			
		||||
	load_x  ra, PORT_CONTEXT_mepcOFFSET(sp) /* Note for starting the scheduler the exception return address is used as the function return address. */
 | 
			
		||||
	load_x  x2, PORT_CONTEXT_xOFFSET(2)(sp)
 | 
			
		||||
	mret
 | 
			
		||||
	addi	sp, sp, portCONTEXT_SIZE
 | 
			
		||||
	ret
 | 
			
		||||
	.endfunc
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
@ -652,7 +360,7 @@ xPortStartFirstTask:
 | 
			
		||||
 * a1, and pvParameters in a2.  The new top of stack is passed out in a0.
 | 
			
		||||
 *
 | 
			
		||||
 * RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
 | 
			
		||||
 * for the 'I' profile, X1 to X15 for the 'E' profile).
 | 
			
		||||
 * for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
 | 
			
		||||
 *
 | 
			
		||||
 * Register		ABI Name	Description						Saver
 | 
			
		||||
 * x0			zero		Hard-wired zero					-
 | 
			
		||||
@ -671,44 +379,36 @@ xPortStartFirstTask:
 | 
			
		||||
 * The RISC-V context is saved t FreeRTOS tasks in the following stack frame,
 | 
			
		||||
 * where the global and thread pointers are currently assumed to be constant so
 | 
			
		||||
 * are not saved:
 | 
			
		||||
 * The RISC-V context is saved t FreeRTOS tasks in the following stack frame:
 | 
			
		||||
 *
 | 
			
		||||
 * ruf (in order to be 16 bytes aligned)
 | 
			
		||||
 * ruf (in order to be 16 bytes aligned)
 | 
			
		||||
 * pxCode - mepc
 | 
			
		||||
 * mstatus
 | 
			
		||||
 * x31 (Only for 'I' profile)
 | 
			
		||||
 * x30 (Only for 'I' profile)
 | 
			
		||||
 * x29 (Only for 'I' profile)
 | 
			
		||||
 * x28 (Only for 'I' profile)
 | 
			
		||||
 * x27 (Only for 'I' profile)
 | 
			
		||||
 * x26 (Only for 'I' profile)
 | 
			
		||||
 * x25 (Only for 'I' profile)
 | 
			
		||||
 * x24 (Only for 'I' profile)
 | 
			
		||||
 * x23 (Only for 'I' profile)
 | 
			
		||||
 * x22 (Only for 'I' profile)
 | 
			
		||||
 * x21 (Only for 'I' profile)
 | 
			
		||||
 * x20 (Only for 'I' profile)
 | 
			
		||||
 * x19 (Only for 'I' profile)
 | 
			
		||||
 * x18 (Only for 'I' profile)
 | 
			
		||||
 * x17 (Only for 'I' profile)
 | 
			
		||||
 * x16 (Only for 'I' profile)
 | 
			
		||||
 * x31
 | 
			
		||||
 * x30
 | 
			
		||||
 * x29
 | 
			
		||||
 * x28
 | 
			
		||||
 * x27
 | 
			
		||||
 * x26
 | 
			
		||||
 * x25
 | 
			
		||||
 * x24
 | 
			
		||||
 * x23
 | 
			
		||||
 * x22
 | 
			
		||||
 * x21
 | 
			
		||||
 * x20
 | 
			
		||||
 * x19
 | 
			
		||||
 * x18
 | 
			
		||||
 * x17
 | 
			
		||||
 * x16
 | 
			
		||||
 * x15
 | 
			
		||||
 * x14
 | 
			
		||||
 * x13
 | 
			
		||||
 * x12
 | 
			
		||||
 * x11
 | 
			
		||||
 * pvParameters - x10 (a0)
 | 
			
		||||
 * pvParameters
 | 
			
		||||
 * x9
 | 
			
		||||
 * x8
 | 
			
		||||
 * x7
 | 
			
		||||
 * x6
 | 
			
		||||
 * x5
 | 
			
		||||
 * x4 (tp)
 | 
			
		||||
 * x3 (gp)
 | 
			
		||||
 * x2 (sp)
 | 
			
		||||
 * portTASK_RETURN_ADDRESS - x1 (ra)
 | 
			
		||||
 * x0
 | 
			
		||||
 * portTASK_RETURN_ADDRESS
 | 
			
		||||
 * [chip specific registers go here]
 | 
			
		||||
 * pxCode
 | 
			
		||||
 */
 | 
			
		||||
@ -720,75 +420,24 @@ pxPortInitialiseStack:
 | 
			
		||||
	andi t0, t0, ~0x8					/* Ensure interrupts are disabled when the stack is restored within an ISR.  Required when a task is created after the schedulre has been started, otherwise interrupts would be disabled anyway. */
 | 
			
		||||
	addi t1, x0, 0x188					/* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
 | 
			
		||||
	slli t1, t1, 4
 | 
			
		||||
	not t2, t1							/* reset previous value */
 | 
			
		||||
	and t0, t0, t2
 | 
			
		||||
	or t0, t0, t1						/* Set MPIE and MPP bits in mstatus value. */
 | 
			
		||||
 | 
			
		||||
	/* Make room for the registers. */
 | 
			
		||||
	addi	t2, a0, -portasmREGISTER_CONTEXT_WORDSIZE
 | 
			
		||||
	
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(1)(t2)	/* x1(ra)		Return address */
 | 
			
		||||
	store_x  a0,  PORT_CONTEXT_xOFFSET(2)(t2)	/* x2(sp) 		Stack pointer */
 | 
			
		||||
	store_x  x3,  PORT_CONTEXT_xOFFSET(3)(t2)	/* x3(gp)		Global pointer */
 | 
			
		||||
	store_x  x4,  PORT_CONTEXT_xOFFSET(4)(t2)	/* x4(tp)		Thread pointer */
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(5)(t2)	/* x5(t0)		Temporaries */
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(6)(t2)	/* x6(t1)		Temporaries */
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(7)(t2)	/* x7(t2)		Temporaries */
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(8)(t2)	/* x8(s0/fp)	Saved register/Frame pointer */
 | 
			
		||||
	store_x  x0,  PORT_CONTEXT_xOFFSET(9)(t2)	/* x9(s1)		Saved register */
 | 
			
		||||
	store_x  a2, PORT_CONTEXT_xOFFSET(10)(t2)	/* x10(a0)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(11)(t2)	/* x11(a1)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(12)(t2)	/* x12(a2)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(13)(t2)	/* x13(a3)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(14)(t2)	/* x14(a4)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(15)(t2)	/* x15(a5)		Function arguments */
 | 
			
		||||
#ifndef __riscv_32e
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(16)(t2)	/* x16(a6)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(17)(t2)	/* x17(a7)		Function arguments */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(18)(t2)	/* x18(s2)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(19)(t2)	/* x19(s3)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(20)(t2)	/* x20(s4)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(21)(t2)	/* x21(s5)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(22)(t2)	/* x22(s6)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(23)(t2)	/* x23(s7)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(24)(t2)	/* x24(s8)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(25)(t2)	/* x25(s9)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(26)(t2)	/* x26(s10)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(27)(t2)	/* x27(s11)		Saved registers */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(28)(t2)	/* x28(t3)		Temporaries */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(29)(t2)	/* x29(t4)		Temporaries */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(30)(t2)	/* x30(t5)		Temporaries */
 | 
			
		||||
	store_x  x0, PORT_CONTEXT_xOFFSET(31)(t2)	/* x31(t6)		Temporaries */
 | 
			
		||||
#endif /* __riscv_32e */
 | 
			
		||||
 | 
			
		||||
	store_x a1, PORT_CONTEXT_mepcOFFSET(t2)
 | 
			
		||||
	store_x t0, PORT_CONTEXT_mstatusOFFSET(t2)
 | 
			
		||||
 | 
			
		||||
	/* The number of additional registers. */
 | 
			
		||||
	addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE 
 | 
			
		||||
	addi a0, a0, -portWORD_SIZE
 | 
			
		||||
	store_x t0, 0(a0)					/* mstatus onto the stack. */
 | 
			
		||||
	addi a0, a0, -(22 * portWORD_SIZE)	/* Space for registers x11-x31. */
 | 
			
		||||
	store_x a2, 0(a0)					/* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */
 | 
			
		||||
	addi a0, a0, -(6 * portWORD_SIZE)	/* Space for registers x5-x9. */
 | 
			
		||||
	store_x x0, 0(a0)					/* Return address onto the stack, could be portTASK_RETURN_ADDRESS */
 | 
			
		||||
	addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
 | 
			
		||||
chip_specific_stack_frame:				/* First add any chip specific registers to the stack frame being created. */
 | 
			
		||||
	beq t0, x0, 1f						/* No more chip specific registers to save. */
 | 
			
		||||
	addi t2, t2, -portWORD_SIZE			/* Make space for chip specific register. */
 | 
			
		||||
	store_x x0, 0(t2)					/* Give the chip specific register an initial value of zero. */
 | 
			
		||||
	addi a0, a0, -portWORD_SIZE			/* Make space for chip specific register. */
 | 
			
		||||
	store_x x0, 0(a0)					/* Give the chip specific register an initial value of zero. */
 | 
			
		||||
	addi t0, t0, -1						/* Decrement the count of chip specific registers remaining. */
 | 
			
		||||
	j chip_specific_stack_frame			/* Until no more chip specific registers. */
 | 
			
		||||
1:
 | 
			
		||||
 | 
			
		||||
	#ifdef __riscv_fdiv
 | 
			
		||||
		/* Make room for the fpu registers. */
 | 
			
		||||
		/* Here we use the memory space needed for all fpu registers instead of using the number of fpu registers */
 | 
			
		||||
		/* Thanks to it we usually manage any xxbits core with yybits fpu */
 | 
			
		||||
		addi t0, x0, portasmFPU_CONTEXT_WORDSIZE
 | 
			
		||||
	fpu_specific_stack_frame:
 | 
			
		||||
		beq t0, x0, 1f						/* No more space is needed. */
 | 
			
		||||
		addi t2, t2, -portWORD_SIZE
 | 
			
		||||
		store_x x0, 0(t2)					/* Give an initial value of zero. */
 | 
			
		||||
		addi t0, t0, -portWORD_SIZE			/* Decrement the count space remaining. */
 | 
			
		||||
		j fpu_specific_stack_frame			/* Until no more space is needed. */
 | 
			
		||||
	1:	
 | 
			
		||||
	#endif /* __riscv_fdiv */
 | 
			
		||||
 | 
			
		||||
	mv a0, t2
 | 
			
		||||
	addi a0, a0, -portWORD_SIZE
 | 
			
		||||
	store_x a1, 0(a0)					/* mret value (pxCode parameter) onto the stack. */
 | 
			
		||||
	ret
 | 
			
		||||
	.endfunc
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user