System Device Configuration
- group System Device Configuration
Functions for system and clock setup available in system_<device>.c.
Nuclei provides a template file system_Device.c that must be adapted by the silicon vendor to match their actual device. As a minimum requirement, this file must provide:
A device-specific system configuration function, SystemInit.
Global c library _premain_init and _postmain_fini functions called right before calling main function.
A global variable that contains the system frequency, SystemCoreClock.
A global eclic configuration initialization, ECLIC_Init.
A global exception and trap configuration initialization, Trap_Init and Exception_Init.
Vendor customized interrupt, exception and nmi handling code, see Interrupt and Exception and NMI Handling
The file configures the device and, typically, initializes the oscillator (PLL) that is part of the microcontroller device. This file might export other functions or variables that provide a more flexible configuration of the microcontroller system.
And this file also provided common interrupt, exception and NMI exception handling framework template, Silicon vendor can customize these template code as they want.
- Attention
Be aware that a value stored to
SystemCoreClock
during low level initialization (i.e.SystemInit()
) might get overwritten by C libray startup code and/or .bss section initialization. Thus its highly recommended to call SystemCoreClockUpdate at the beginning of the usermain()
routine.
Note
Please pay special attention to the static variable
SystemCoreClock
. This variable might be used throughout the whole system initialization and runtime to calculate frequency/time related values. Thus one must assure that the variable always reflects the actual system clock speed.Defines
-
CLINT_MSIP(base, hartid) (*(volatile uint32_t *)((uintptr_t)((base) + ((hartid) * 4))))
-
SMP_CTRLREG(base, ofs) (*(volatile uint32_t *)((uintptr_t)((base) + (ofs))))
Functions
-
void exc_entry_s(void)
-
void irq_entry_s(void)
default entry for s-mode non-vector irq entry
-
void default_intexc_handler(void)
default entry for s-mode exception entry
default eclic interrupt or exception interrupt handler
-
void SystemCoreClockUpdate(void)
Function to update the variable SystemCoreClock.
Updates the variable SystemCoreClock and must be called whenever the core clock is changed during program execution. The function evaluates the clock register settings and calculates the current core clock.
-
void SystemInit(void)
Function to Initialize the system.
Initializes the microcontroller system. Typically, this function configures the oscillator (PLL) that is part of the microcontroller device. For systems with a variable clock speed, it updates the variable SystemCoreClock. SystemInit is called from the file startup.
-
void SystemBannerPrint(void)
Banner Print for Nuclei SDK.
-
void irq_entry(void)
-
void exc_entry(void)
-
void ECLIC_Interrupt_Init(void)
Do ECLIC Interrupt configuration.
This function will initialize cpu interrupt mode to eclic mode. It will
set common non-vector entry to irq_entry
set vector interrupt table to vector_base
set exception entry to exc_entry
set eclic mth to 0, and nlbits to the bigest bits it supports
set s-mode common non-vector entry to irq_entry_s if tee present
set s-mode vector interrupt table to vector_base_s if tee present
set s-mode exception entry to exc_entry_s if tee present
set eclic sth to 0 if tee present
-
void CLINT_Interrupt_Init(void)
Do CLINT Interrupt configuration.
This function will initialize cpu interrupt mode to clint mode. It will
Set exception/interrupt entry to exc_entry, now interrupt and exception share the same entry point
Register interrupt handling routine system_core_interrupt_handler to core_interrupt_handler function, which will be called in core_exception_handler function
-
void PLIC_Interrupt_Init(void)
Do PLIC Interrupt configuration.
This function will initialize cpu interrupt mode to clint/plic mode. It will
Initialize a software maintained SystemM/SExtInterruptHandlers and SystemCoreInterruptHandlers to default value
Set exception/interrupt entry to exc_entry, now interrupt and exception share the same entry point
-
void Interrupt_Init(void)
initialize interrupt controller
Do CPU interrupt initialization, if plic present, init it, then init eclic if present. So if ECLIC present, the interrupt will default configured to ECLIC interrupt mode, if you want to switch to PLIC interrupt mode, you need to call PLIC_Interrupt_Init in you application code.
By default, if ECLIC present, eclic interrupt mode will be set, otherwise it will be clint/plic interrupt mode
Remark
This function previously was ECLIC_Init, now ECLIC_Init is removed
-
int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void *handler)
Initialize a specific IRQ and register the handler.
This function set vector mode, trigger mode and polarity, interrupt level and priority, assign handler for specific IRQn.
Remark
This function use to configure specific eclic interrupt and register its interrupt handler and enable its interrupt.
If the vector table is placed in read-only section(FLASHXIP mode), handler could not be installed
- Parameters:
IRQn – [in] NMI interrupt handler address
shv – [in] ECLIC_NON_VECTOR_INTERRUPT means non-vector mode, and ECLIC_VECTOR_INTERRUPT is vector mode
trig_mode – [in] see ECLIC_TRIGGER_Type
lvl – [in] interupt level
priority – [in] interrupt priority
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
int32_t Core_Register_IRQ(uint32_t irqn, void *handler)
Register a m-mode riscv core interrupt and register the handler.
This function set interrupt handler for core interrupt in non-eclic mode
Remark
This function use to configure riscv core interrupt and register its interrupt handler and enable its interrupt.
You can only use it when you are not in eclic interrupt mode
- Parameters:
irqn – [in] interrupt number
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
int32_t Core_Register_IRQ_S(uint32_t irqn, void *handler)
Register a riscv s-mode core interrupt and register the handler.
This function set interrupt handler for core interrupt in non-eclic mode
Remark
This function use to configure riscv core interrupt and register its interrupt handler and enable its interrupt.
You can only use it when you are not in eclic interrupt mode
- Parameters:
irqn – [in] interrupt number
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
int32_t PLIC_Register_IRQ(uint32_t source, uint8_t priority, void *handler)
Register a m-mode specific plic interrupt and register the handler.
This function set priority and handler for m-mode plic interrupt
Remark
This function use to configure specific plic interrupt and register its interrupt handler and enable its interrupt.
You can only use it when you are in plic interrupt mode
- Parameters:
source – [in] interrupt source
priority – [in] interrupt priority
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
int32_t PLIC_Register_IRQ_S(uint32_t source, uint8_t priority, void *handler)
Register a s-mode specific plic interrupt and register the handler.
This function set priority and handler for s-mode plic interrupt
Remark
This function use to configure specific plic interrupt and register its interrupt handler and enable its interrupt.
You can only use it when you are in plic interrupt mode
- Parameters:
source – [in] interrupt source
priority – [in] interrupt priority
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
int32_t ECLIC_Register_IRQ_S(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void *handler)
Initialize a specific IRQ and register the handler for supervisor mode.
This function set vector mode, trigger mode and polarity, interrupt level and priority, assign handler for specific IRQn.
Remark
This function use to configure specific eclic S-mode interrupt and register its interrupt handler and enable its interrupt.
If the vector table is placed in read-only section (FLASHXIP mode), handler could not be installed.
- Parameters:
IRQn – [in] NMI interrupt handler address
shv – [in] ECLIC_NON_VECTOR_INTERRUPT means non-vector mode, and ECLIC_VECTOR_INTERRUPT is vector mode
trig_mode – [in] see ECLIC_TRIGGER_Type
lvl – [in] interupt level
priority – [in] interrupt priority
handler – [in] interrupt handler, if NULL, handler will not be installed
- Returns:
-1 means invalid input parameter. 0 means successful.
-
void __sync_harts(void)
Synchronize all harts.
This function is used to synchronize all the harts, especially to wait the boot hart finish initialization of data section, bss section and c runtines initialization This function must be placed in .text.init section, since section initialization is not ready, global variable and static variable should be avoid to use in this function, and avoid to call other functions
-
static void Trap_Init(void)
do the init for trap
-
void _premain_init(void)
early init function before main
This function is executed right before main function. For RISC-V gnu toolchain, _init function might not be called by __libc_init_array function, so we defined a new function to do initialization.
-
void _postmain_fini(int status)
finish function after main
This function is executed right after main function. For RISC-V gnu toolchain, _fini function might not be called by __libc_fini_array function, so we defined a new function to do initialization
- Parameters:
status – [in] status code return from main
-
void _init(void)
_init function called in __libc_init_array()
This
__libc_init_array()
function is called during startup code, user need to implement this function, otherwise when link it will error init.c:(.text.__libc_init_array+0x26): undefined reference to _initNote
Please use _premain_init function now
-
void _fini(void)
_fini function called in __libc_fini_array()
This
__libc_fini_array()
function is called when exit main. user need to implement this function, otherwise when link it will error fini.c:(.text.__libc_fini_array+0x28): undefined reference to _finiNote
Please use _postmain_fini function now
Variables
-
uint32_t SystemCoreClock = SYSTEM_CLOCK
Variable to hold the system core clock value.
Holds the system core clock, which is the system clock frequency supplied to the SysTick timer and the processor core clock. This variable can be used by debuggers to query the frequency of the debug timer or to configure the trace clock speed.
- Attention
Compilers must be configured to avoid removing this variable in case the application program is not using it. Debugging systems require the variable to be physically present in memory so that it can be examined to configure the debugger.
-
unsigned long vector_base[]
-
unsigned long CpuIRegionBase = 0xFFFFFFFF
Nuclei RISC-V CPU IRegion Base Address Probed, you should avoid to use it in your application code, please use __IREGION_BASEADDR if you want.
Interrupt Exception NMI Handling
- group Interrupt and Exception and NMI Handling
Functions for interrupt, exception and nmi handle available in system_<device>.c.
Nuclei provide a template for interrupt, exception and NMI handling. Silicon Vendor could adapat according to their requirement. Silicon vendor could implement interface for different exception code and replace current implementation.
Defines
-
MAX_SYSTEM_EXCEPTION_NUM 20
Max exception handler number, don’t include the NMI(0xFFF) one.
-
SYSTEM_CORE_INTNUM 16
Typedefs
-
typedef void (*EXC_HANDLER)(unsigned long cause, unsigned long sp)
Exception Handler Function Typedef.
Note
This typedef is only used internal in this system_<Device>.c file. It is used to do type conversion for registered exception handler before calling it.
-
typedef void (*INT_HANDLER)(unsigned long cause, unsigned long sp)
Functions
-
static void system_mmode_extirq_handler(unsigned long exccode, unsigned long sp)
M-Mode external interrupt handler common entry for plic interrupt mode.
This function provide common entry for m-mode external interrupt for plic interrupt mode.
- Parameters:
exccode – [in] exception code indicating the reason that caused the trap in machine mode
sp – [in] stack pointer
-
static void core_interrupt_handler(unsigned long exccode, unsigned long sp)
M-Mode Common Interrupt handler entry when in clint/plic mode.
This function provided a command entry for interrupt in clint/plic mode
Remark
This is not used for clic interrupt mode, which is only used for clint/plic interrupt mode, you should call CLINT_Interrupt_Init or PLIC_Interrupt_Init first to make sure this handler entry registered
If you are not in eclic interrupt mode, please use please use Interrupt_Register_CoreIRQ to register internal interrupt and use Interrupt_Register_ExtIRQ to register external interrupt
- Parameters:
exccode – [in] Exception Code
sp – [in] stack pointer
-
uint32_t core_exception_handler(unsigned long mcause, unsigned long sp)
M-Mode Common NMI/Exception/Interrupt handler entry.
This function provided a command entry for NMI and exception. Silicon Vendor could modify this template implementation according to requirement.
Remark
RISCV provided common entry for all types of exception and interrupt if not in eclic mode. This is proposed code template for exception entry function, Silicon Vendor could modify the implementation.
For the core_exception_handler template, we provided exception register function Exception_Register_EXC which can help developer to register your exception handler for specific exception number.
If you are in eclic interrupt mode, please use ECLIC_Register_IRQ to register both internal and external interrupt
If you are not in eclic interrupt mode, please use please use Interrupt_Register_CoreIRQ to register internal interrupt and use Interrupt_Register_ExtIRQ to register external interrupt
- Parameters:
mcause – [in] code indicating the reason that caused the trap in machine mode
sp – [in] stack pointer
-
static void system_default_interrupt_handler_s(unsigned long scause, unsigned long sp)
s-mode System Default Interrupt Handler for CLINT/PLIC Interrupt Mode
This function provided a default interrupt handling code for all interrupt ids.
-
static void system_smode_extirq_handler(unsigned long exccode, unsigned long sp)
S-Mode external interrupt handler common entry for plic interrupt mode.
This function provide common entry for s-mode external interrupt for plic interrupt mode.
- Parameters:
exccode – [in] exception code indicating the reason that caused the trap in supervisor mode
sp – [in] stack pointer
-
static void core_interrupt_handler_s(unsigned long exccode, unsigned long sp)
S-Mode Common Interrupt handler entry when in clint/plic mode.
This function provided a command entry for interrupt in clint/plic mode
Remark
This is not used for clic interrupt mode, which is only used for clint/plic interrupt mode, you should call CLINT_Interrupt_Init or PLIC_Interrupt_Init first to make sure this handler entry registered
If you are not in eclic interrupt mode, please use please use Interrupt_Register_CoreIRQ to register internal interrupt and use Interrupt_Register_ExtIRQ to register external interrupt
- Parameters:
exccode – [in] Exception Code
sp – [in] stack pointer
-
void Exception_DumpFrame(unsigned long sp, uint8_t mode)
Dump Exception Frame.
This function provided feature to dump exception frame stored in stack.
- Parameters:
sp – [in] stackpoint
mode – [in] privileged mode to decide whether to dump msubm CSR
-
static void system_default_interrupt_handler(unsigned long mcause, unsigned long sp)
M-Mode System Default Interrupt Handler for CLINT/PLIC Interrupt Mode.
This function provided a default interrupt handling code for all interrupt ids.
-
void Interrupt_Register_CoreIRQ(uint32_t irqn, unsigned long int_handler)
Register a m-mode core interrupt handler for core interrupt number.
For irqn <= SYSTEM_CORE_INTNUM, it will be registered into SystemCoreInterruptHandlers[irqn-1], only used in non-eclic mode.
Remark
You can only use it when you are not in ECLIC interrupt mode.
- Parameters:
irqn – See IRQn
int_handler – The core interrupt handler for this interrupt code irqn
-
unsigned long Interrupt_Get_CoreIRQ(uint32_t irqn)
Get a m-mode core interrupt handler for core interrupt number.
Remark
You can only use it when you are not in ECLIC interrupt mode.
- Parameters:
irqn – See IRQn
- Returns:
The core interrupt handler for this interrupt code irqn, only used in non-eclic mode.
-
void Interrupt_Register_ExtIRQ(uint32_t irqn, unsigned long int_handler)
Register a m-mode external interrupt handler for plic external interrupt number.
For irqn <= __PLIC_INTNUM, it will be registered into SystemMExtInterruptHandlers[irqn-1].
Remark
You can only use it when you are in PLIC interrupt mode.
- Parameters:
irqn – See IRQn
int_handler – The external interrupt handler for this interrupt code irqn
-
unsigned long Interrupt_Get_ExtIRQ(uint32_t irqn)
Get a m-mode external interrupt handler for external interrupt number.
Remark
You can only use it when you are in PLIC interrupt mode.
- Parameters:
irqn – See IRQn
- Returns:
The external interrupt handler for this interrupt code irqn
-
void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler)
Register a m-mode exception handler for exception code EXCn.
For EXCn < MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers[EXCn-1].
For EXCn == NMI_EXCn, it will be registered into SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM].
- Parameters:
EXCn – [in] See EXCn_Type
exc_handler – [in] The exception handler for this exception code EXCn
-
unsigned long Exception_Get_EXC(uint32_t EXCn)
Get current m-mode exception handler for exception code EXCn.
For EXCn < MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers[EXCn-1].
For EXCn == NMI_EXCn, it will return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM].
- Parameters:
EXCn – [in] See EXCn_Type
- Returns:
Current exception handler for exception code EXCn, if not found, return 0.
-
static void Exception_Init(void)
Initialize all the default core exception handlers.
The core exception handler for each exception id will be initialized to system_default_exception_handler.
Note
Called in _init function, used to initialize default exception handlers for all exception IDs SystemExceptionHandlers contains NMI, but SystemExceptionHandlers_S not, because NMI can’t be delegated to S-mode.
-
uint32_t core_exception_handler_s(unsigned long scause, unsigned long sp)
common Exception handler entry of supervisor mode
This function provided a supervisor mode common entry for exception. Silicon Vendor could modify this template implementation according to requirement.
Remark
RISCV provided supervisor mode common entry for all types of exception. This is proposed code template for exception entry function, Silicon Vendor could modify the implementation.
For the core_exception_handler_s template, we provided exception register function Exception_Register_EXC_S which can help developer to register your exception handler for specific exception number.
- Parameters:
scause – [in] code indicating the reason that caused the trap in supervisor mode
sp – [in] stack pointer
-
void Exception_Register_EXC_S(uint32_t EXCn, unsigned long exc_handler)
Register an exception handler for exception code EXCn of supervisor mode.
-For EXCn < MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers_S[EXCn-1]. -For EXCn == NMI_EXCn, The NMI (Non-maskable-interrupt) cannot be trapped to the supervisor-mode or user-mode for any configuration, so NMI won’t be registered into SystemExceptionHandlers_S.
- Parameters:
EXCn – [in] See EXCn_Type
exc_handler – [in] The exception handler for this exception code EXCn
-
unsigned long Exception_Get_EXC_S(uint32_t EXCn)
Get current exception handler for exception code EXCn of supervisor mode.
For EXCn < MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers_S[EXCn-1].
- Parameters:
EXCn – [in] See EXCn_Type
- Returns:
Current exception handler for exception code EXCn, if not found, return 0.
-
void Interrupt_Register_CoreIRQ_S(uint32_t irqn, unsigned long int_handler)
Register an s-mode core interrupt handler for core interrupt number.
For irqn <= SYSTEM_CORE_INTNUM, it will be registered into SystemCoreInterruptHandlers[irqn-1], only used in non-eclic mode.
Remark
You can only use it when you are not in ECLIC interrupt mode.
- Parameters:
irqn – See IRQn
int_handler – The core interrupt handler for this interrupt code irqn
-
unsigned long Interrupt_Get_CoreIRQ_S(uint32_t irqn)
Get a s-mode core interrupt handler for core interrupt number.
Remark
You can only use it when you are not in ECLIC interrupt mode.
- Parameters:
irqn – See IRQn
- Returns:
The core interrupt handler for this interrupt code irqn, only used in non-eclic mode.
-
void Interrupt_Register_ExtIRQ_S(uint32_t irqn, unsigned long int_handler)
Register an s-mode external interrupt handler for plic external interrupt number.
For irqn <= __PLIC_INTNUM, it will be registered into SystemSExtInterruptHandlers[irqn-1].
Remark
You can only use it when you are in PLIC interrupt mode.
- Parameters:
irqn – See IRQn
int_handler – The external interrupt handler for this interrupt code irqn
-
unsigned long Interrupt_Get_ExtIRQ_S(uint32_t irqn)
Get an s-mode external interrupt handler for external interrupt number.
Remark
You can only use it when you are in PLIC interrupt mode.
- Parameters:
irqn – See IRQn
- Returns:
The external interrupt handler for this interrupt code irqn
-
static void system_default_exception_handler(unsigned long mcause, unsigned long sp)
M-Mode System Default Exception Handler.
This function provides a default exception and NMI handler for all exception ids. By default, It will just print some information for debug, Vendor can customize it according to its requirements.
- Parameters:
mcause – [in] code indicating the reason that caused the trap in machine mode
sp – [in] stack pointer
-
static void system_default_exception_handler_s(unsigned long scause, unsigned long sp)
Supervisor mode system Default Exception Handler.
This function provided a default supervisor mode exception and NMI handling code for all exception ids. By default, It will just print some information for debug, Vendor can customize it according to its requirements.
- Parameters:
scause – [in] code indicating the reason that caused the trap in supervisor mode
sp – [in] stack pointer
Variables
-
static unsigned long SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM + 1]
Store the exception handlers for each exception ID.
Note
This SystemExceptionHandlers are used to store all the handlers for all the exception codes Nuclei N/NX core provided.
Exception code 0 - 19, totally 20 exceptions are mapped to SystemExceptionHandlers[0:19]
Exception for NMI is also re-routed to exception handling(exception code 0xFFF) in startup code configuration, the handler itself is mapped to SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]
-
static unsigned long SystemMExtInterruptHandlers[__PLIC_INTNUM]
-
static unsigned long SystemCoreInterruptHandlers[SYSTEM_CORE_INTNUM]
-
static INT_HANDLER system_core_interrupt_handler = NULL
-
static unsigned long SystemExceptionHandlers_S[MAX_SYSTEM_EXCEPTION_NUM]
Store the exception handlers for each exception ID in supervisor mode.
Note
This SystemExceptionHandlers_S are used to store all the handlers for all the exception codes Nuclei N/NX core provided.
Exception code 0 - 19, totally 20 exceptions are mapped to SystemExceptionHandlers_S[0:19]
-
static INT_HANDLER system_core_interrupt_handler_s = NULL
-
static unsigned long SystemCoreInterruptHandlers_S[SYSTEM_CORE_INTNUM]
-
static unsigned long SystemSExtInterruptHandlers[__PLIC_INTNUM]
-
MAX_SYSTEM_EXCEPTION_NUM 20