@@ -897,6 +897,36 @@ __STATIC_INLINE void __switch_mode(uint8_t mode, uintptr_t stack, void(*entry_po
897897 __ASM volatile ("mret" );
898898}
899899
900+ /**
901+ * \brief switch privilege from supervisor mode to others.
902+ * \details
903+ * Execute into \ref entry_point in \ref mode(user) with given stack
904+ * \param mode privilege mode
905+ * \param stack predefined stack, size should set enough
906+ * \param entry_point a function pointer to execute
907+ */
908+ __STATIC_INLINE void __s_switch_mode (uint8_t mode , uintptr_t stack , void (* entry_point )(void ))
909+ {
910+ unsigned long val = 0 ;
911+
912+ /* Set SPP to the requested privilege mode */
913+ val = __RV_CSR_READ (CSR_SSTATUS );
914+ val = __RV_INSERT_FIELD (val , SSTATUS_SPP , mode );
915+
916+ /* Set previous SIE disabled */
917+ val = __RV_INSERT_FIELD (val , SSTATUS_SPIE , 0 );
918+
919+ __RV_CSR_WRITE (CSR_SSTATUS , val );
920+
921+ /* Set the entry point in SEPC */
922+ __RV_CSR_WRITE (CSR_SEPC , (unsigned long )entry_point );
923+
924+ /* Set the register file */
925+ __ASM volatile ("mv sp, %0" ::"r" (stack ));
926+
927+ __ASM volatile ("sret" );
928+ }
929+
900930/**
901931 * \brief Enable IRQ Interrupts
902932 * \details Enables IRQ interrupts by setting the MIE-bit in the MSTATUS Register.
0 commit comments