| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #ifndef _AGM_INTERRUPT_H
- #define _AGM_INTERRUPT_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "util.h"
- #define MCAUSE_INT_MASK (0x80000000)
- static inline void INT_SetISR(void *isr) { write_csr(mtvec, isr); }
- static inline void INT_EnableIntGlobal(void) { set_csr (mstatus, MSTATUS_MIE); }
- static inline void INT_DisableIntGlobal(void) { clear_csr(mstatus, MSTATUS_MIE); }
- static inline void INT_EnableIntExternal(void) { set_csr (mie, MIP_MEIP); }
- static inline void INT_DisableIntExternal(void) { clear_csr(mie, MIP_MEIP); }
- static inline void INT_EnableIntSoftware(void) { set_csr (mie, MIP_MSIP); }
- static inline void INT_DisableIntSoftware(void) { clear_csr(mie, MIP_MSIP); }
- static inline void INT_EnableIntTimer(void) { set_csr (mie, MIP_MTIP); }
- static inline void INT_DisableIntTimer(void) { clear_csr(mie, MIP_MTIP); }
- static inline void INT_EnableIntLocal (uint32_t irq) { set_csr (mie, (1 << irq)); } // irq must be one of LOCAL_INTx_IRQn
- static inline void INT_DisableIntLocal(uint32_t irq) { clear_csr(mie, (1 << irq)); }
- static inline void INT_EnablePLIC(void) { INT_EnableIntExternal(); INT_EnableIntGlobal(); }
- // Each interrupt has an enable bit, a pending bit, and a priority. The pending bits are set regardless of the enable
- // bits. Reading the claim_complete register will return the highest priority pending interrupt number and clear the
- // corresponding pending bit (only for enabled interrupts with above threshold priority). Since Interrupts are numbered
- // starting from 1, a read value of 0 means no active interrupt. A write to the claim_complete register will complete
- // the interrupt.
- typedef struct
- {
- __IO uint32_t PRIORITY[0x400]; // 0x0000-
- __IO uint32_t PENDING[0x400]; // 0x1000-
- __IO uint32_t ENABLE[0x7f800]; // 0x2000-
- __IO uint32_t THRESHOLD; // 0x200000
- __IO uint32_t CLAIM_COMPLETE; // 0x200004
- } PLIC_TypeDef;
- #define PLIC_BASE (0xc000000)
- #define PLIC ((PLIC_TypeDef *) PLIC_BASE)
- #define PLIC_MIN_PRIORITY 1
- // The IRQ number can be greater than word size (XLEN_BITS)
- #define IRQ_BIT_OFFSET(__irq) (__irq % XLEN_BITS)
- #define IRQ_WORD_OFFSET(__irq) (__irq / XLEN_BITS)
- // PLIC functions. INT_ClaimIRQ and INT_CompleteIRQ should be called only within an ISR!
- static inline uint32_t INT_GetIRQThreshold(void) { return PLIC->THRESHOLD; }
- static inline uint32_t INT_GetIRQPriorify(uint32_t irq) { return PLIC->PRIORITY[irq]; }
- static inline uint32_t INT_ClaimIRQ(void) { return PLIC->CLAIM_COMPLETE; }
- static inline void INT_SetIRQThreshold(uint32_t threshold) { PLIC->THRESHOLD = threshold; }
- static inline void INT_SetIRQPriority(uint32_t irq, uint32_t priority) { PLIC->PRIORITY[irq] = priority; }
- static inline void INT_CompleteIRQ(uint32_t irq) { PLIC->CLAIM_COMPLETE = irq; }
- void INT_EnableIRQ(uint32_t irq, uint32_t priority);
- void INT_DisableIRQ(uint32_t irq);
- bool INT_IsIRQPending(uint32_t irq);
- typedef struct
- {
- __IO uint32_t MSIP; // 0x0000, Machine software interrupt pending
- uint32_t RESERVED0[0x0fff];
- __IO uint32_t MTIMECMP_LO; // 0x4000, Machine timer compare
- __IO uint32_t MTIMECMP_HI;
- uint32_t RESERVED1[0x1ffc];
- __IO uint32_t MTIME_LO; // 0xbff8, Machine timer
- __IO uint32_t MTIME_HI;
- } CLINT_TypeDef;
- #undef CLINT_BASE
- #define CLINT_BASE (0x2000000)
- #define CLINT ((CLINT_TypeDef *) CLINT_BASE)
- // CLINT functions
- static inline uint64_t INT_GetMtime(void) { return ((uint64_t)CLINT->MTIME_HI) << 32 | CLINT->MTIME_LO; }
- static inline uint64_t INT_GetMtimeCmp(void) { return ((uint64_t)CLINT->MTIMECMP_HI) << 32 | CLINT->MTIMECMP_LO; }
- static inline void INT_SetMtimeLo(uint32_t mtime) { CLINT->MTIME_LO = mtime; }
- static inline void INT_SetMtimeHi(uint32_t mtime) { CLINT->MTIME_HI = mtime; }
- static inline void INT_SetMtime(uint64_t mtime)
- {
- CLINT->MTIME_LO = 0; // So that MTIME_HI will not inadvertently increase
- CLINT->MTIME_HI = mtime >> 32;
- CLINT->MTIME_LO = mtime;
- }
- static inline void INT_SetMtimeCmp(uint64_t mtime)
- {
- CLINT->MTIMECMP_LO = -1; // So that interrupt is not triggered by an intermediate mtimecmp value
- CLINT->MTIMECMP_HI = mtime >> 32;
- CLINT->MTIMECMP_LO = mtime;
- }
- static inline void INT_TriggerSoftwareInt(void) { CLINT->MSIP = 1; }
- static inline void INT_ClearSoftwareInt(void) { CLINT->MSIP = 0; }
- // ISR functions
- extern void handle_trap_nonest(uintptr_t mcause, uintptr_t mepc, uintptr_t *sp);
- extern void handle_trap_nested(uintptr_t mcause, uintptr_t mepc, uintptr_t *sp);
- extern void (**plic_isr)(void);
- extern void (**clint_isr)(void);
- extern void exception_handler(void);
- void INT_Init(void);
- #ifdef __cplusplus
- }
- #endif
- #endif
|