Interrupts and Exceptions

Description

This section explains how to use interrupts and exceptions and access functions for the Enhanced Core Local Interrupt Controller(ECLIC).

Nuclei provides a template file startup_device for each supported compiler. The file must be adapted by the silicon vendor to include interrupt vectors for all device-specific interrupt handlers. Each interrupt handler is defined as a weak function to an dummy handler. These interrupt handlers can be used directly in application software without being adapted by the programmer.

Click Interrupt to learn more about interrupt handling in Nuclei processor core.

NMI Interrupt

NMI interrupt entry is stored by CSR_MNVEC. If CSR_MMSIC[9] is 1 then NMI entry is the same as Exception which get from CSR_MTVEC. If CSR_MMSIC[9] is 1 NMI entry is reset vector.

Exception

Exception has only 1 entry address which stored by CSR_MTVEC. All the exceptions will jump to the same entry exc_entry defined in intexc_<Device>.S.

The table below lists the core exception code of the Nuclei N/NX processors.

Core exception code of the Nuclei N/NX processors

Exception Code

Value

Description

InsUnalign_EXCn

0

Instruction address misaligned

InsAccFault_EXCn

1

Instruction access fault

IlleIns_EXCn

2

Illegal instruction

Break_EXCn

3

Beakpoint

LdAddrUnalign_EXCn

4

Load address misaligned

LdFault_EXCn

5

Load access fault

StAddrUnalign_EXCn

6

Store or AMO address misaligned

StAccessFault_EXCn

7

Store or AMO access fault

UmodeEcall_EXCn

8

Environment call from User mode

SmodeEcall_EXCn

9

Environment call from Supervisor Mode

MmodeEcall_EXCn

11

Environment call from Machine mode

InsPageFault_EXCn

12

Instruction page fault

LdPageFault_EXCn

13

Load page fault

StPageFault_EXCn

15

Store or AMO page fault

StackOverflow_EXCn

24

Stack overflow fault

StackUnderflow_EXCn

25

Stack overflow fault

NMI_EXCn

0xfff

NMI interrupt

Vector Table

The Vector Table defines the entry addresses of the ECLIC managed interrupts.

It is typically located at the beginning of the program memory, and you can modify CSR MTVT to reallocate the base address of this vector table, but you need to take care of the base address alignment according to the number of interrupts.

base address alignment according to the number of interrupts

Number of Interrupt

Alignment Requirements of CSR MTVT

0 to 16

64-byte

17 to 32

128-byte

33 to 64

256-byte

65 to 128

512-byte

129 to 256

1KB

257 to 512

2KB

513 to 1024

4KB

Interrupt number 0~18 is reserved by Nuclei Core. 19~1023 could be used by Silicon Vendor Device.

Below is an example interrupt allocated table:

 1typedef enum IRQn {
 2    /******  Nuclei N/NX Processor Core Internal Interrupt Numbers *************************/
 3    Reserved0_IRQn               =   0,     /*!<  Internal reserved                        */
 4    Reserved1_IRQn               =   1,     /*!<  Internal reserved                        */
 5    Reserved2_IRQn               =   2,     /*!<  Internal reserved                        */
 6    SysTimerSW_IRQn              =   3,     /*!<  System Timer SW interrupt                */
 7    Reserved3_IRQn               =   4,     /*!<  Internal reserved                        */
 8    Reserved4_IRQn               =   5,     /*!<  Internal reserved                        */
 9    Reserved5_IRQn               =   6,     /*!<  Internal reserved                        */
10    SysTimer_IRQn                =   7,     /*!<  System Timer Interrupt                   */
11    Reserved6_IRQn               =   8,     /*!<  Internal reserved                        */
12    Reserved7_IRQn               =   9,     /*!<  Internal reserved                        */
13    Reserved8_IRQn               =  10,     /*!<  Internal reserved                        */
14    Reserved9_IRQn               =  11,     /*!<  Internal reserved                        */
15    Reserved10_IRQn              =  12,     /*!<  Internal reserved                        */
16    Reserved11_IRQn              =  13,     /*!<  Internal reserved                        */
17    Reserved12_IRQn              =  14,     /*!<  Internal reserved                        */
18    Reserved13_IRQn              =  15,     /*!<  Internal reserved                        */
19    Reserved14_IRQn              =  16,     /*!<  Internal reserved                        */
20    HardFault_IRQn               =  17,     /*!<  Hard Fault, storage access error         */
21    Reserved15_IRQn              =  18,     /*!<  Internal reserved                        */
22
23    /******  GD32VF103 Specific External Interrupt Numbers *********************************/
24    WWDGT_IRQn                   =  19,     /*!< window watchDog timer interrupt           */
25    LVD_IRQn                     =  20,     /*!< LVD through EXTI line detect interrupt    */
26    TAMPER_IRQn                  =  21,     /*!< tamper through EXTI line detect           */
27                 :       :
28                 :       :
29    CAN1_EWMC_IRQn               =  85,     /*!< CAN1 EWMC interrupt                       */
30    USBFS_IRQn                   =  86,     /*!< USBFS global interrupt                    */
31    SOC_INT_MAX,                            /*!< Number of total Interrupts                */
32} IRQn_Type;

ECLIC API Definitions

When macro NMSIS_ECLIC_VIRTUAL is defined, the ECLIC access functions in the table below must be implemented for virtualizing ECLIC access.

These functions should be implemented in a separate source module. The original NMSIS-Core __ECLIC_xxx functions are always available independent of NMSIS_ECLIC_VIRTUAL macro.

ECLIC Access Functions

ECLIC ACCESS FUNCTIONS

NMSIS-CORE FUNCTIONS FOR ECLIC

ECLIC_SetCfgNlbits

__ECLIC_SetCfgNlbits()

ECLIC_GetCfgNlbits

__ECLIC_GetCfgNlbits()

ECLIC_GetInfoVer

__ECLIC_GetInfoVer()

ECLIC_GetInfoCtlbits

__ECLIC_GetInfoCtlbits()

ECLIC_GetInfoNum

__ECLIC_GetInfoNum()

ECLIC_SetMth

__ECLIC_SetMth()

ECLIC_GetMth

__ECLIC_GetMth()

ECLIC_EnableIRQ

__ECLIC_EnableIRQ()

ECLIC_GetEnableIRQ

__ECLIC_GetEnableIRQ()

ECLIC_DisableIRQ

__ECLIC_DisableIRQ()

ECLIC_SetPendingIRQ

__ECLIC_SetPendingIRQ()

ECLIC_GetPendingIRQ

__ECLIC_GetPendingIRQ()

ECLIC_ClearPendingIRQ

__ECLIC_ClearPendingIRQ()

ECLIC_SetTrigIRQ

__ECLIC_SetTrigIRQ()

ECLIC_GetTrigIRQ

__ECLIC_GetTrigIRQ()

ECLIC_SetShvIRQ

__ECLIC_SetShvIRQ()

ECLIC_GetShvIRQ

__ECLIC_GetShvIRQ()

ECLIC_SetCtrlIRQ

__ECLIC_SetCtrlIRQ()

ECLIC_GetCtrlIRQ

__ECLIC_GetCtrlIRQ()

ECLIC_SetLevelIRQ

__ECLIC_SetLevelIRQ()

ECLIC_GetLevelIRQ

__ECLIC_GetLevelIRQ()

ECLIC_SetPriorityIRQ

__ECLIC_SetPriorityIRQ()

ECLIC_GetPriorityIRQ

__ECLIC_GetPriorityIRQ()

When NMSIS_VECTAB_VIRTUAL macro is defined, the functions in the table below must be replaced to virtualize the API access functions to the interrupt vector table.

The ECLIC vector table API should be implemented in a separate source module.

This allows, for example, alternate implementations to relocate the vector table from flash to RAM on the first vector table update.

The original NMSIS-Core functions are always available, but prefixed with __ECLIC.

ECLIC Vector Access Functions

ECLIC Vector Table Access

NMSIS-CORE FUNCTIONS

ECLIC_SetVector

__ECLIC_SetVector()

ECLIC_GetVector

__ECLIC_GetVector()

ECLIC Function Usage

The code below shows the usage of various NMSIS ECLIC flow with an GD32VF103 device.

gd32vf103_interrupt_example1.c
 1#include "gd32vf103.h"
 2
 3// Vector interrupt which could be nested
 4__INTERRUPT void eclic_button1_handler(void)
 5{
 6    SAVE_IRQ_CSR_CONTEXT();                                           /* save mepc,mcause,msubm enable interrupts */
 7
 8    GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << GREEN_LED_GPIO_OFFSET);        /* Green LED On */
 9    GPIO_REG(GPIO_RISE_IP) = (0x1 << BUTTON_1_GPIO_OFFSET);           /* Clear the GPIO Pending interrupt by writing 1. */
10
11    RESTORE_IRQ_CSR_CONTEXT();                                        /* disable interrupts,restore mepc,mcause,msubm */
12}
13
14// Non-vector interrupt
15void eclic_button2_handler(void)
16{
17    GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << GREEN_LED_GPIO_OFFSET);        /* Green LED On */
18    GPIO_REG(GPIO_RISE_IP) = (0x1 << BUTTON_2_GPIO_OFFSET);           /* Clear the GPIO Pending interrupt by writing 1. */
19}
20
21void eclic_global_initialize(void)
22{
23    ECLIC_SetMth(0);
24    ECLIC_SetCfgNlbits(3);
25}
26
27int eclic_register_interrupt(IRQn_Type IRQn, uint8_t shv, uint32_t trig_mode, uint32 lvl, uint32_t priority, void * handler)
28{
29    ECLIC_SetShvIRQ(IRQn, shv);
30    ECLIC_SetTrigIRQ(IRQn, trig_mode);
31    ECLIC_SetLevelIRQ(IRQn, lvl);
32    ECLIC_SetPriorityIRQ(IRQn, priority);
33    ECLIC_SetVector(IRQn, (rv_csr_t)(handler));
34    ECLIC_EnableIRQ(IRQn);
35    return 0;
36}
37
38int main (void)
39{
40    uint32_t returnCode;
41
42    eclic_global_initialize();                                /* initialize ECLIC */
43
44    GPIO_init();                                              /* initialize GPIO */
45
46    returnCode = eclic_register_interrupt(BTN1_IRQn,1,2,1,0,Button1_IRQHandler);  /* register system button1 interrupt */
47    returnCode = eclic_register_interrupt(BTN2_IRQn,0,2,2,0,Button2_IRQHandler);  /* register system button2 interrupt */
48
49    __enable_irq();                                           /* enable global interrupt */
50
51    if (returnCode != 0)  {                                   /* Check return code for errors */
52      // Error Handling
53    }
54
55    while(1);
56}

Interrupt and Exception API

enum IRQn

Values:

enumerator Reserved0_IRQn
enumerator Reserved1_IRQn
enumerator Reserved2_IRQn
enumerator SysTimerSW_IRQn
enumerator Reserved3_IRQn
enumerator Reserved4_IRQn
enumerator Reserved5_IRQn
enumerator SysTimer_IRQn
enumerator Reserved6_IRQn
enumerator Reserved7_IRQn
enumerator Reserved8_IRQn
enumerator Reserved9_IRQn
enumerator Reserved10_IRQn
enumerator Reserved11_IRQn
enumerator Reserved12_IRQn
enumerator Reserved13_IRQn
enumerator Reserved14_IRQn
enumerator Reserved15_IRQn
enumerator Reserved16_IRQn
enumerator FirstDeviceSpecificInterrupt_IRQn
enumerator SOC_INT_MAX
__STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits (uint32_t nlbits)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits (void)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer (void)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits (void)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum (void)
__STATIC_FORCEINLINE void __ECLIC_SetMth (uint8_t mth)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetMth (void)
__STATIC_FORCEINLINE void __ECLIC_EnableIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_DisableIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ (IRQn_Type IRQn, uint32_t trig)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ (IRQn_Type IRQn, uint32_t shv)
__STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ (IRQn_Type IRQn, uint8_t intctrl)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ (IRQn_Type IRQn, uint8_t lvl_abs)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ (IRQn_Type IRQn, uint8_t pri)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetVector (IRQn_Type IRQn, rv_csr_t vector)
__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetModeIRQ (IRQn_Type IRQn, uint32_t mode)
__STATIC_FORCEINLINE void __ECLIC_SetSth (uint8_t sth)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetSth (void)
__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ_S (IRQn_Type IRQn, uint32_t trig)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetTrigIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ_S (IRQn_Type IRQn, uint32_t shv)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetShvIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ_S (IRQn_Type IRQn, uint8_t intctrl)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ_S (IRQn_Type IRQn, uint8_t lvl_abs)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ_S (IRQn_Type IRQn, uint8_t pri)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_EnableIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE uint8_t __ECLIC_GetEnableIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_DisableIRQ_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __ECLIC_SetVector_S (IRQn_Type IRQn, rv_csr_t vector)
__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector_S (IRQn_Type IRQn)
__STATIC_FORCEINLINE void __set_exc_entry (rv_csr_t addr)
__STATIC_FORCEINLINE rv_csr_t __get_exc_entry (void)
__STATIC_FORCEINLINE void __set_nonvec_entry (rv_csr_t addr)
__STATIC_FORCEINLINE rv_csr_t __get_nonvec_entry (void)
__STATIC_FORCEINLINE rv_csr_t __get_nmi_entry (void)
ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
ECLIC_GetInfoVer __ECLIC_GetInfoVer
ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
ECLIC_GetInfoNum __ECLIC_GetInfoNum
ECLIC_SetMth __ECLIC_SetMth
ECLIC_GetMth __ECLIC_GetMth
ECLIC_EnableIRQ __ECLIC_EnableIRQ
ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
ECLIC_DisableIRQ __ECLIC_DisableIRQ
ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
ECLIC_SetModeIRQ __ECLIC_SetModeIRQ
ECLIC_SetSth __ECLIC_SetSth
ECLIC_GetSth __ECLIC_GetSth
ECLIC_SetTrigIRQ_S __ECLIC_SetTrigIRQ_S
ECLIC_GetTrigIRQ_S __ECLIC_GetTrigIRQ_S
ECLIC_SetShvIRQ_S __ECLIC_SetShvIRQ_S
ECLIC_GetShvIRQ_S __ECLIC_GetShvIRQ_S
ECLIC_SetCtrlIRQ_S __ECLIC_SetCtrlIRQ_S
ECLIC_GetCtrlIRQ_S __ECLIC_GetCtrlIRQ_S
ECLIC_SetLevelIRQ_S __ECLIC_SetLevelIRQ_S
ECLIC_GetLevelIRQ_S __ECLIC_GetLevelIRQ_S
ECLIC_SetPriorityIRQ_S __ECLIC_SetPriorityIRQ_S
ECLIC_GetPriorityIRQ_S __ECLIC_GetPriorityIRQ_S
ECLIC_EnableIRQ_S __ECLIC_EnableIRQ_S
ECLIC_GetEnableIRQ_S __ECLIC_GetEnableIRQ_S
ECLIC_DisableIRQ_S __ECLIC_DisableIRQ_S
ECLIC_SetVector __ECLIC_SetVector
ECLIC_GetVector __ECLIC_GetVector
ECLIC_SetVector_S __ECLIC_SetVector_S
ECLIC_GetVector_S __ECLIC_GetVector_S
SAVE_IRQ_CSR_CONTEXT()
SAVE_IRQ_CSR_CONTEXT_S()
RESTORE_IRQ_CSR_CONTEXT()
RESTORE_IRQ_CSR_CONTEXT_S()
group NMSIS_Core_IntExc

Functions that manage interrupts and exceptions via the ECLIC.

Defines

ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
ECLIC_GetInfoVer __ECLIC_GetInfoVer
ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
ECLIC_GetInfoNum __ECLIC_GetInfoNum
ECLIC_SetMth __ECLIC_SetMth
ECLIC_GetMth __ECLIC_GetMth
ECLIC_EnableIRQ __ECLIC_EnableIRQ
ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
ECLIC_DisableIRQ __ECLIC_DisableIRQ
ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
ECLIC_SetModeIRQ __ECLIC_SetModeIRQ
ECLIC_SetSth __ECLIC_SetSth
ECLIC_GetSth __ECLIC_GetSth
ECLIC_SetTrigIRQ_S __ECLIC_SetTrigIRQ_S
ECLIC_GetTrigIRQ_S __ECLIC_GetTrigIRQ_S
ECLIC_SetShvIRQ_S __ECLIC_SetShvIRQ_S
ECLIC_GetShvIRQ_S __ECLIC_GetShvIRQ_S
ECLIC_SetCtrlIRQ_S __ECLIC_SetCtrlIRQ_S
ECLIC_GetCtrlIRQ_S __ECLIC_GetCtrlIRQ_S
ECLIC_SetLevelIRQ_S __ECLIC_SetLevelIRQ_S
ECLIC_GetLevelIRQ_S __ECLIC_GetLevelIRQ_S
ECLIC_SetPriorityIRQ_S __ECLIC_SetPriorityIRQ_S
ECLIC_GetPriorityIRQ_S __ECLIC_GetPriorityIRQ_S
ECLIC_EnableIRQ_S __ECLIC_EnableIRQ_S
ECLIC_GetEnableIRQ_S __ECLIC_GetEnableIRQ_S
ECLIC_DisableIRQ_S __ECLIC_DisableIRQ_S
ECLIC_SetVector __ECLIC_SetVector
ECLIC_GetVector __ECLIC_GetVector
ECLIC_SetVector_S __ECLIC_SetVector_S
ECLIC_GetVector_S __ECLIC_GetVector_S
SAVE_IRQ_CSR_CONTEXT()

Save necessary CSRs into variables for vector interrupt nesting.

This macro is used to declare variables which are used for saving CSRs(MCAUSE, MEPC, MSUB), and it will read these CSR content into these variables, it need to be used in a vector-interrupt if nesting is required.

Remark

  • Interrupt will be enabled after this macro is called

  • It need to be used together with RESTORE_IRQ_CSR_CONTEXT

  • Don’t use variable names __mcause, __mpec, __msubm in your ISR code

  • If you want to enable interrupt nesting feature for vector interrupt, you can do it like this:

    // __INTERRUPT attribute will generates function entry and exit sequences suitable
    // for use in an interrupt handler when this attribute is present
    __INTERRUPT void eclic_mtip_handler(void)
    {
        // Must call this to save CSRs
        SAVE_IRQ_CSR_CONTEXT();
        // !!!Interrupt is enabled here!!!
        // !!!Higher priority interrupt could nest it!!!
    
        // put you own interrupt handling code here
    
        // Must call this to restore CSRs
        RESTORE_IRQ_CSR_CONTEXT();
    }
    

SAVE_IRQ_CSR_CONTEXT_S()

Save necessary CSRs into variables for vector interrupt nesting in supervisor mode.

RESTORE_IRQ_CSR_CONTEXT()

Restore necessary CSRs from variables for vector interrupt nesting.

This macro is used restore CSRs(MCAUSE, MEPC, MSUB) from pre-defined variables in SAVE_IRQ_CSR_CONTEXT macro.

Remark

  • Interrupt will be disabled after this macro is called

  • It need to be used together with SAVE_IRQ_CSR_CONTEXT

RESTORE_IRQ_CSR_CONTEXT_S()

Restore necessary CSRs from variables for vector interrupt nesting in supervisor mode.

Enums

enum IRQn

Definition of IRQn numbers.

The core interrupt enumeration names for IRQn values are defined in the file <Device>.h.

  • Interrupt ID(IRQn) from 0 to 18 are reserved for core internal interrupts.

  • Interrupt ID(IRQn) start from 19 represent device-specific external interrupts.

  • The first device-specific interrupt has the IRQn value 19.

The table below describes the core interrupt names and their availability in various Nuclei Cores.

Values:

enumerator Reserved0_IRQn

Internal reserved.

enumerator Reserved1_IRQn

Internal reserved.

enumerator Reserved2_IRQn

Internal reserved.

enumerator SysTimerSW_IRQn

System Timer SW interrupt.

enumerator Reserved3_IRQn

Internal reserved.

enumerator Reserved4_IRQn

Internal reserved.

enumerator Reserved5_IRQn

Internal reserved.

enumerator SysTimer_IRQn

System Timer Interrupt.

enumerator Reserved6_IRQn

Internal reserved.

enumerator Reserved7_IRQn

Internal reserved.

enumerator Reserved8_IRQn

Internal reserved.

enumerator Reserved9_IRQn

Internal reserved.

enumerator Reserved10_IRQn

Internal reserved.

enumerator Reserved11_IRQn

Internal reserved.

enumerator Reserved12_IRQn

Internal reserved.

enumerator Reserved13_IRQn

Internal reserved.

enumerator Reserved14_IRQn

Internal reserved.

enumerator Reserved15_IRQn

Internal reserved.

enumerator Reserved16_IRQn

Internal reserved.

enumerator FirstDeviceSpecificInterrupt_IRQn

First Device Specific Interrupt.

enumerator SOC_INT_MAX

Number of total interrupts.

Functions

__STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits (uint32_t nlbits)

Set nlbits value.

This function set the nlbits value of CLICCFG register.

Remark

  • nlbits is used to set the width of level in the CLICINTCTL[i].

See also

  • ECLIC_GetCfgNlbits

Parameters

nlbits[in] nlbits value

__STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits (void)

Get nlbits value.

This function get the nlbits value of CLICCFG register.

Remark

  • nlbits is used to set the width of level in the CLICINTCTL[i].

See also

  • ECLIC_SetCfgNlbits

Returns

nlbits value of CLICCFG register

__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer (void)

Get the ECLIC version number.

This function gets the hardware version information from CLICINFO register.

Remark

  • This function gets harware version information from CLICINFO register.

  • Bit 20:17 for architecture version, bit 16:13 for implementation version.

See also

  • ECLIC_GetInfoNum

Returns

hardware version number in CLICINFO register.

__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits (void)

Get CLICINTCTLBITS.

This function gets CLICINTCTLBITS from CLICINFO register.

Remark

  • In the CLICINTCTL[i] registers, with 2 <= CLICINTCTLBITS <= 8.

  • The implemented bits are kept left-justified in the most-significant bits of each 8-bit CLICINTCTL[I] register, with the lower unimplemented bits treated as hardwired to 1.

See also

  • ECLIC_GetInfoNum

Returns

CLICINTCTLBITS from CLICINFO register.

__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum (void)

Get number of maximum interrupt inputs supported.

This function gets number of maximum interrupt inputs supported from CLICINFO register.

Remark

  • This function gets number of maximum interrupt inputs supported from CLICINFO register.

  • The num_interrupt field specifies the actual number of maximum interrupt inputs supported in this implementation.

See also

  • ECLIC_GetInfoCtlbits

Returns

number of maximum interrupt inputs supported from CLICINFO register.

__STATIC_FORCEINLINE void __ECLIC_SetMth (uint8_t mth)

Set Machine Mode Interrupt Level Threshold.

This function sets machine mode interrupt level threshold.

See also

  • ECLIC_GetMth

Parameters

mth[in] Interrupt Level Threshold.

__STATIC_FORCEINLINE uint8_t __ECLIC_GetMth (void)

Get Machine Mode Interrupt Level Threshold.

This function gets machine mode interrupt level threshold.

See also

  • ECLIC_SetMth

Returns

Interrupt Level Threshold.

__STATIC_FORCEINLINE void __ECLIC_EnableIRQ (IRQn_Type IRQn)

Enable a specific interrupt.

This function enables the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_DisableIRQ

Parameters

IRQn[in] Interrupt number

__STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ (IRQn_Type IRQn)

Get a specific interrupt enable status.

This function returns the interrupt enable status for the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_EnableIRQ

  • ECLIC_DisableIRQ

Parameters

IRQn[in] Interrupt number

Returns

  • 0 Interrupt is not enabled

  • 1 Interrupt is pending

__STATIC_FORCEINLINE void __ECLIC_DisableIRQ (IRQn_Type IRQn)

Disable a specific interrupt.

This function disables the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_EnableIRQ

Parameters

IRQn[in] Number of the external interrupt to disable

__STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ (IRQn_Type IRQn)

Get the pending specific interrupt.

This function returns the pending status of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetPendingIRQ

  • ECLIC_ClearPendingIRQ

Parameters

IRQn[in] Interrupt number

Returns

  • 0 Interrupt is not pending

  • 1 Interrupt is pending

__STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ (IRQn_Type IRQn)

Set a specific interrupt to pending.

This function sets the pending bit for the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetPendingIRQ

  • ECLIC_ClearPendingIRQ

Parameters

IRQn[in] Interrupt number

__STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ (IRQn_Type IRQn)

Clear a specific interrupt from pending.

This function removes the pending state of the specific interrupt IRQn. IRQn cannot be a negative number.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetPendingIRQ

  • ECLIC_GetPendingIRQ

Parameters

IRQn[in] Interrupt number

__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ (IRQn_Type IRQn, uint32_t trig)

Set trigger mode and polarity for a specific interrupt.

This function set trigger mode and polarity of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetTrigIRQ

Parameters
__STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ (IRQn_Type IRQn)

Get trigger mode and polarity for a specific interrupt.

This function get trigger mode and polarity of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetTrigIRQ

Parameters

IRQn[in] Interrupt number

Returns

__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ (IRQn_Type IRQn, uint32_t shv)

Set interrupt working mode for a specific interrupt.

This function set selective hardware vector or non-vector working mode of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetShvIRQ

Parameters
__STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ (IRQn_Type IRQn)

Get interrupt working mode for a specific interrupt.

This function get selective hardware vector or non-vector working mode of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetShvIRQ

Parameters

IRQn[in] Interrupt number

Returns

shv

__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ (IRQn_Type IRQn, uint8_t intctrl)

Modify ECLIC Interrupt Input Control Register for a specific interrupt.

This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetCtrlIRQ

Parameters
  • IRQn[in] Interrupt number

  • intctrl[in] Set value for CLICINTCTL[i] register

__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ (IRQn_Type IRQn)

Get ECLIC Interrupt Input Control Register value for a specific interrupt.

This function modify ECLIC Interrupt Input Control register of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetCtrlIRQ

Parameters

IRQn[in] Interrupt number

Returns

value of ECLIC Interrupt Input Control register

__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ (IRQn_Type IRQn, uint8_t lvl_abs)

Set ECLIC Interrupt level of a specific interrupt.

This function set interrupt level of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.

  • When you set level value you need use clciinfo.nlbits to get the width of level. Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are present in the CLICINTCTL register.

See also

  • ECLIC_GetLevelIRQ

Parameters
  • IRQn[in] Interrupt number

  • lvl_abs[in] Interrupt level

__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ (IRQn_Type IRQn)

Get ECLIC Interrupt level of a specific interrupt.

This function get interrupt level of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetLevelIRQ

Parameters

IRQn[in] Interrupt number

Returns

Interrupt level

__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ (IRQn_Type IRQn, uint8_t pri)

Get ECLIC Interrupt priority of a specific interrupt.

This function get interrupt priority of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • If pri to be set is larger than the max priority allowed, it will be force to be max priority.

  • Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits is less than CLICINTCTLBITS. Otherwise priority width is 0.

See also

  • ECLIC_GetPriorityIRQ

Parameters
  • IRQn[in] Interrupt number

  • pri[in] Interrupt priority

__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ (IRQn_Type IRQn)

Get ECLIC Interrupt priority of a specific interrupt.

This function get interrupt priority of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetPriorityIRQ

Parameters

IRQn[in] Interrupt number

Returns

Interrupt priority

__STATIC_FORCEINLINE void __ECLIC_SetVector (IRQn_Type IRQn, rv_csr_t vector)

Set Interrupt Vector of a specific interrupt.

This function set interrupt handler address of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • You can set the CSR_CSR_MTVT to set interrupt vector table entry address.

  • If your vector table is placed in readonly section, the vector for IRQn will not be modified. For this case, you need to use the correct irq handler name defined in your vector table as your irq handler function name.

  • This function will only work correctly when the vector table is placed in an read-write enabled section.

See also

  • ECLIC_GetVector

Parameters
  • IRQn[in] Interrupt number

  • vector[in] Interrupt handler address

__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector (IRQn_Type IRQn)

Get Interrupt Vector of a specific interrupt.

This function get interrupt handler address of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • You can read CSR_CSR_MTVT to get interrupt vector table entry address.

See also

  • ECLIC_SetVector

Parameters

IRQn[in] Interrupt number

Returns

Interrupt handler address

__STATIC_FORCEINLINE void __ECLIC_SetModeIRQ (IRQn_Type IRQn, uint32_t mode)

Set privilege mode of a specific interrupt.

This function set in which privilege mode the interrupts IRQn should be taken.

Remark

  • IRQn must not be negative.

  • mode must be 1(Supervisor Mode) or 3(Machine Mode), other values are ignored.

  • M-mode can R/W this field, but S-mode can only read.And ECLIC with TEE does not reply on CSR mideleg to delegate interrupts.

  • Mode of S-mode ECLIC region’s clicintattr can be omitted to set, which is mirror to M-mode ECLIC region’s. Only the low 6 bits of clicintattr [i] can be written via the S-mode memory region.

Parameters
  • IRQn[in] Interrupt number

  • mode[in] Privilege mode

__STATIC_FORCEINLINE void __ECLIC_SetSth (uint8_t sth)

Set supervisor-mode Interrupt Level Threshold in supervisor mode.

This function sets supervisor-mode interrupt level threshold.

Remark

  • S-mode ECLIC region sintthresh’sth is a mirror to M-mode ECLIC region’s mintthresh.sth, and will be updated synchronously, here operate on mintthresh.sth.

See also

  • ECLIC_GetSth

Parameters

sth[in] Interrupt Level Threshold.

__STATIC_FORCEINLINE uint8_t __ECLIC_GetSth (void)

Get supervisor-mode Interrupt Level Threshold in supervisor mode.

This function gets supervisor mode interrupt level threshold.

Remark

  • S-mode ECLIC region sintthresh’sth is a mirror to M-mode ECLIC region’s mintthresh.sth, and will be updated synchronously, here operate on mintthresh.sth.

See also

  • ECLIC_SetSth

Returns

Interrupt Level Threshold.

__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ_S (IRQn_Type IRQn, uint32_t trig)

Set trigger mode and polarity for a specific interrupt in supervisor mode.

This function set trigger mode and polarity of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetTrigIRQ_S

Parameters
__STATIC_FORCEINLINE uint8_t __ECLIC_GetTrigIRQ_S (IRQn_Type IRQn)

Get trigger mode and polarity for a specific interrupt in supervisor mode.

This function get trigger mode and polarity of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetTrigIRQ_S

Parameters

IRQn[in] Interrupt number

Returns

__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ_S (IRQn_Type IRQn, uint32_t shv)

Set interrupt working mode for a specific interrupt in supervisor mode.

This function set selective hardware vector or non-vector working mode of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetShvIRQ_S

Parameters
__STATIC_FORCEINLINE uint8_t __ECLIC_GetShvIRQ_S (IRQn_Type IRQn)

Get interrupt working mode for a specific interrupt in supervisor mode.

This function get selective hardware vector or non-vector working mode of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SMODE_SetShvIRQ

Parameters

IRQn[in] Interrupt number

Returns

shv

__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ_S (IRQn_Type IRQn, uint8_t intctrl)

Modify ECLIC Interrupt Input Control Register for a specific interrupt in supervisor mode.

This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_GetCtrlIRQ_S

Parameters
  • IRQn[in] Interrupt number

  • intctrl[in] Set value for CLICINTCTL[i] register

__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ_S (IRQn_Type IRQn)

Get ECLIC Interrupt Input Control Register value for a specific interrupt in supervisor mode.

This function modify ECLIC Interrupt Input Control register of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetCtrlIRQ_S

Parameters

IRQn[in] Interrupt number

Returns

value of ECLIC Interrupt Input Control register

__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ_S (IRQn_Type IRQn, uint8_t lvl_abs)

Set ECLIC Interrupt level of a specific interrupt in supervisor mode.

This function set interrupt level of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.

  • When you set level value you need use clciinfo.nlbits to get the width of level. Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are present in the CLICINTCTL register.

See also

  • ECLIC_GetLevelIRQ_S

Parameters
  • IRQn[in] Interrupt number

  • lvl_abs[in] Interrupt level

__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ_S (IRQn_Type IRQn)

Get ECLIC Interrupt level of a specific interrupt.

This function get interrupt level of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetLevelIRQ_S

Parameters

IRQn[in] Interrupt number

Returns

Interrupt level

__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ_S (IRQn_Type IRQn, uint8_t pri)

Set ECLIC Interrupt priority of a specific interrupt in supervisor mode.

This function get interrupt priority of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • If pri to be set is larger than the max priority allowed, it will be force to be max priority.

  • Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits is less than CLICINTCTLBITS. Otherwise priority width is 0.

See also

  • ECLIC_GetPriorityIRQ_S

Parameters
  • IRQn[in] Interrupt number

  • pri[in] Interrupt priority

__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ_S (IRQn_Type IRQn)

Get ECLIC Interrupt priority of a specific interrupt in supervisor mode.

This function get interrupt priority of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_SetPriorityIRQ_S

Parameters

IRQn[in] Interrupt number

Returns

Interrupt priority

__STATIC_FORCEINLINE void __ECLIC_EnableIRQ_S (IRQn_Type IRQn)

Enable a specific interrupt in supervisor mode.

This function enables the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_DisableIRQ

Parameters

IRQn[in] Interrupt number

__STATIC_FORCEINLINE uint8_t __ECLIC_GetEnableIRQ_S (IRQn_Type IRQn)

Get a specific interrupt enable status in supervisor mode.

This function returns the interrupt enable status for the specific interrupt IRQn in S MODE.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_EnableIRQ_S

  • ECLIC_DisableIRQ_S

Parameters

IRQn[in] Interrupt number

Returns

  • 0 Interrupt is not masked

  • 1 Interrupt is enabled

__STATIC_FORCEINLINE void __ECLIC_DisableIRQ_S (IRQn_Type IRQn)

Disable a specific interrupt in supervisor mode.

This function disables the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

See also

  • ECLIC_EnableIRQ

Parameters

IRQn[in] Number of the external interrupt to disable

__STATIC_FORCEINLINE void __ECLIC_SetVector_S (IRQn_Type IRQn, rv_csr_t vector)

Set Interrupt Vector of a specific interrupt in supervisor mode.

This function set interrupt handler address of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • You can set the CSR_CSR_MTVT to set interrupt vector table entry address.

  • If your vector table is placed in readonly section, the vector for IRQn will not be modified. For this case, you need to use the correct irq handler name defined in your vector table as your irq handler function name.

  • This function will only work correctly when the vector table is placed in an read-write enabled section.

See also

  • ECLIC_GetVector_S

Parameters
  • IRQn[in] Interrupt number

  • vector[in] Interrupt handler address

__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector_S (IRQn_Type IRQn)

Get Interrupt Vector of a specific interrupt in supervisor mode.

This function get interrupt handler address of the specific interrupt IRQn.

Remark

  • IRQn must not be negative.

  • You can read CSR_CSR_MTVT to get interrupt vector table entry address.

See also

  • ECLIC_SMODE_SetVector

Parameters

IRQn[in] Interrupt number

Returns

Interrupt handler address

__STATIC_FORCEINLINE void __set_exc_entry (rv_csr_t addr)

Set Exception entry address.

This function set exception handler address to ‘CSR_MTVEC’.

Remark

  • This function use to set exception handler address to ‘CSR_MTVEC’. Address need to be aligned to 64 bytes.

See also

  • __get_exc_entry

Parameters

addr[in] Exception handler address

__STATIC_FORCEINLINE rv_csr_t __get_exc_entry (void)

Get Exception entry address.

This function get exception handler address from ‘CSR_MTVEC’.

Remark

  • This function use to get exception handler address from ‘CSR_MTVEC’. Address need to be aligned to 64 bytes.

See also

  • __set_exc_entry

Returns

Exception handler address

__STATIC_FORCEINLINE void __set_nonvec_entry (rv_csr_t addr)

Set Non-vector interrupt entry address.

This function set Non-vector interrupt address.

Remark

  • This function use to set non-vector interrupt entry address to ‘CSR_MTVT2’ if

  • CSR_MTVT2 bit0 is 1. If ‘CSR_MTVT2’ bit0 is 0 then set address to ‘CSR_MTVEC’

See also

  • __get_nonvec_entry

Parameters

addr[in] Non-vector interrupt entry address

__STATIC_FORCEINLINE rv_csr_t __get_nonvec_entry (void)

Get Non-vector interrupt entry address.

This function get Non-vector interrupt address.

Remark

  • This function use to get non-vector interrupt entry address from ‘CSR_MTVT2’ if

  • CSR_MTVT2 bit0 is 1. If ‘CSR_MTVT2’ bit0 is 0 then get address from ‘CSR_MTVEC’.

See also

  • __set_nonvec_entry

Returns

Non-vector interrupt handler address

__STATIC_FORCEINLINE rv_csr_t __get_nmi_entry (void)

Get NMI interrupt entry from ‘CSR_MNVEC’.

This function get NMI interrupt address from ‘CSR_MNVEC’.

Remark

  • This function use to get NMI interrupt handler address from ‘CSR_MNVEC’. If CSR_MMISC_CTL[9] = 1 ‘CSR_MNVEC’

  • will be equal as mtvec. If CSR_MMISC_CTL[9] = 0 ‘CSR_MNVEC’ will be equal as reset vector.

  • NMI entry is defined via CSR_MMISC_CTL, writing to CSR_MNVEC will be ignored.

Returns

NMI interrupt handler address