IoT_SCV_CH584M/RVMSIS/core_riscv.h

695 lines
20 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : core_riscv.h
* Author : WCH
* Version : V1.0.0
* Date : 2024/07/25
* Description : CH585 Series RISC-V Core Peripheral Access Layer Header File
*********************************************************************************
* Copyright (c) 2024 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CORE_RISCV_H__
#define __CORE_RISCV_H__
#ifdef __cplusplus
extern "C" {
#endif
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
/* IO definitions */
#ifdef __cplusplus
#define __I volatile /*!< defines 'read only' permissions */
#else
#define __I volatile const /*!< defines 'read only' permissions */
#endif
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
#define RV_STATIC_INLINE static inline
//typedef enum {SUCCESS = 0, ERROR = !SUCCESS} ErrorStatus;
typedef enum
{
DISABLE = 0,
ENABLE = !DISABLE
} FunctionalState;
typedef enum
{
RESET = 0,
SET = !RESET
} FlagStatus, ITStatus;
/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */
typedef struct
{
__I uint32_t ISR[8]; // 0
__I uint32_t IPR[8]; // 20H
__IO uint32_t ITHRESDR; // 40H
uint8_t RESERVED[8]; // 44H
__I uint32_t GISR; // 4CH
__IO uint8_t VTFIDR[4]; // 50H
uint8_t RESERVED0[0x0C]; // 54H
__IO uint32_t VTFADDR[4]; // 60H
uint8_t RESERVED1[0x90]; // 70H
__O uint32_t IENR[8]; // 100H
uint8_t RESERVED2[0x60]; // 120H
__O uint32_t IRER[8]; // 180H
uint8_t RESERVED3[0x60]; // 1A0H
__O uint32_t IPSR[8]; // 200H
uint8_t RESERVED4[0x60]; // 220H
__O uint32_t IPRR[8]; // 280H
uint8_t RESERVED5[0x60]; // 2A0H
__IO uint32_t IACTR[8]; // 300H
uint8_t RESERVED6[0xE0]; // 320H
__IO uint8_t IPRIOR[256]; // 400H
uint8_t RESERVED7[0x810]; // 500H
__IO uint32_t SCTLR; // D10H
} PFIC_Type;
/* memory mapped structure for SysTick */
typedef struct
{
__IO uint32_t CTLR;
__IO uint32_t SR;
union
{
__IO uint32_t CNT;
__IO uint32_t CNTL;
};
uint8_t RESERVED[4];
union
{
__IO uint32_t CMP;
__IO uint32_t CMPL;
};
uint8_t RESERVED0[4];
} SysTick_Type;
#define PFIC ((PFIC_Type *)0xE000E000)
#define SysTick ((SysTick_Type *)0xE000F000)
#define PFIC_KEY1 ((uint32_t)0xFA050000)
#define PFIC_KEY2 ((uint32_t)0xBCAF0000)
#define PFIC_KEY3 ((uint32_t)0xBEEF0000)
/* ########################## define #################################### */
#define __nop() __asm__ volatile("nop")
#define read_csr(reg) ({unsigned long __tmp; \
__asm__ volatile ("csrr %0, " #reg : "=r"(__tmp)); \
__tmp; })
#define write_csr(reg, val) ({ \
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
__asm__ volatile ("csrw " #reg ", %0" :: "i"(val)); \
else \
__asm__ volatile ("csrw " #reg ", %0" :: "r"(val)); })
/*********************************************************************
* @fn __risc_v_enable_irq
*
* @brief recover Global Interrupt
*
* @return mpie and mie bit in mstatus.
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __risc_v_enable_irq(uint32_t mpie_mie)
{
uint32_t result;
__asm volatile("csrrs %0, 0x800, %1" : \
"=r"(result): "r"(mpie_mie) : "memory");
return result;
}
/*********************************************************************
* @fn __disable_irq
*
* @brief Disable Global Interrupt
*
* @return mpie and mie bit in mstatus.
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __risc_v_disable_irq(void)
{
uint32_t result;
__asm volatile("csrrc %0, 0x800, %1" : \
"=r"(result): "r"(0x88) : "memory");
return result & 0x88;
}
/* ########################## PFIC functions #################################### */
#define PFIC_EnableAllIRQ() {write_csr(0x800, 0x88);__nop();__nop();}
#define PFIC_DisableAllIRQ() {write_csr(0x800, 0x80);__nop();__nop();}
/*******************************************************************************
* @fn PFIC_EnableIRQ
*
* @brief Enable Interrupt
*
* @param IRQn - Interrupt Numbers
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_EnableIRQ(IRQn_Type IRQn)
{
PFIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/*******************************************************************************
* @fn PFIC_DisableIRQ
*
* @brief Disable Interrupt
*
* @param IRQn - Interrupt Numbers
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_DisableIRQ(IRQn_Type IRQn)
{
PFIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
__nop();
__nop();
}
/*******************************************************************************
* @fn PFIC_GetStatusIRQ
*
* @brief Get Interrupt Enable State
*
* @param IRQn - Interrupt Numbers
*
* @return 1: Interrupt Enable
* 0: Interrupt Disable
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t PFIC_GetStatusIRQ(IRQn_Type IRQn)
{
return ((uint32_t)((PFIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0));
}
/*******************************************************************************
* @fn PFIC_GetPendingIRQ
*
* @brief Get Interrupt Pending State
*
* @param IRQn - Interrupt Numbers
*
* @return 1: Interrupt Pending Enable
* 0: Interrupt Pending Disable
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t PFIC_GetPendingIRQ(IRQn_Type IRQn)
{
return ((uint32_t)((PFIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0));
}
/*******************************************************************************
* @fn PFIC_SetPendingIRQ
*
* @brief Set Interrupt Pending
*
* @param IRQn - Interrupt Numbers
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_SetPendingIRQ(IRQn_Type IRQn)
{
PFIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/*******************************************************************************
* @fn PFIC_ClearPendingIRQ
*
* @brief Clear Interrupt Pending
*
* @param IRQn - Interrupt Numbers
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_ClearPendingIRQ(IRQn_Type IRQn)
{
PFIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/*******************************************************************************
* @fn PFIC_GetActive
*
* @brief Get Interrupt Active State
*
* @param IRQn - Interrupt Numbers
*
* @return 1: Interrupt Active
* 0: Interrupt No Active.
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t PFIC_GetActive(IRQn_Type IRQn)
{
return ((uint32_t)((PFIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0));
}
/*******************************************************************************
* @fn PFIC_SetPriority
*
* @brief Set Interrupt Priority
*
* @param IRQn - Interrupt Numbers
* @param priority - bit7: pre-emption priority
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_SetPriority(IRQn_Type IRQn, uint8_t priority)
{
PFIC->IPRIOR[(uint32_t)(IRQn)] = priority ? 0x80 : 0;
}
/*********************************************************************
* @fn SetVTFIRQ
*
* @brief Set VTF Interrupt
*
* @param addr - VTF interrupt service function base address.
* IRQn - Interrupt Numbers
* num - VTF Interrupt Numbers
* NewState - DISABLE or ENABLE
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState)
{
if (num > 3) return ;
if (NewState != DISABLE)
{
PFIC->VTFIDR[num] = IRQn;
PFIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) | 0x1);
}
else
{
PFIC->VTFIDR[num] = IRQn;
PFIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) & (~0x1));
}
}
/*********************************************************************
* @fn _SEV
*
* @brief Set Event
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void _SEV(void)
{
PFIC->SCTLR |= (1 << 3) | (1 << 5);
}
/*********************************************************************
* @fn _WFE
*
* @brief Wait for Events
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void _WFE(void)
{
PFIC->SCTLR |= (1 << 3);
asm volatile("wfi");
}
/*********************************************************************
* @fn __WFE
*
* @brief Wait for Events
*
* @return None
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __WFE(void)
{
_SEV();
_WFE();
_WFE();
}
/*********************************************************************
* @fn __WFI
*
* @brief Wait for Interrupt
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __WFI(void)
{
PFIC->SCTLR &= ~(1 << 3); // wfi
__asm__ volatile("wfi");
}
/*********************************************************************
* @fn PFIC_SystemReset
*
* @brief Initiate a system reset request
*/
__attribute__((always_inline)) RV_STATIC_INLINE void PFIC_SystemReset(void)
{
PFIC->SCTLR = 0x80000000;
}
/*********************************************************************
* @fn __get_MSTATUS
*
* @brief Return the Machine Status Register
*
* @return mstatus value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MSTATUS(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mstatus" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MSTATUS
*
* @brief Set the Machine Status Register
*
* @param value - set mstatus value
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MSTATUS(uint32_t value)
{
__ASM volatile("csrw mstatus, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MISA
*
* @brief Return the Machine ISA Register
*
* @return misa value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MISA(void)
{
uint32_t result;
__ASM volatile("csrr %0," "misa" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MISA
*
* @brief Set the Machine ISA Register
*
* @param value - set misa value
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MISA(uint32_t value)
{
__ASM volatile("csrw misa, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MTVEC
*
* @brief Return the Machine Trap-Vector Base-Address Register
*
* @return mtvec value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MTVEC(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mtvec" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MTVEC
*
* @brief Set the Machine Trap-Vector Base-Address Register
*
* @param value - set mtvec value
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MTVEC(uint32_t value)
{
__ASM volatile("csrw mtvec, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MSCRATCH
*
* @brief Return the Machine Seratch Register
*
* @return mscratch value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MSCRATCH(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mscratch" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MSCRATCH
*
* @brief Set the Machine Seratch Register
*
* @param value - set mscratch value
*
* @return none
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MSCRATCH(uint32_t value)
{
__ASM volatile("csrw mscratch, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MEPC
*
* @brief Return the Machine Exception Program Register
*
* @return mepc value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MEPC(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mepc" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MEPC
*
* @brief Set the Machine Exception Program Register
*
* @return mepc value
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MEPC(uint32_t value)
{
__ASM volatile("csrw mepc, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MCAUSE
*
* @brief Return the Machine Cause Register
*
* @return mcause value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MCAUSE(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mcause" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MEPC
*
* @brief Set the Machine Cause Register
*
* @return mcause value
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MCAUSE(uint32_t value)
{
__ASM volatile("csrw mcause, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MTVAL
*
* @brief Return the Machine Trap Value Register
*
* @return mtval value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MTVAL(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mtval" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __set_MTVAL
*
* @brief Set the Machine Trap Value Register
*
* @return mtval value
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __set_MTVAL(uint32_t value)
{
__ASM volatile("csrw mtval, %0" : : "r"(value));
}
/*********************************************************************
* @fn __get_MVENDORID
*
* @brief Return Vendor ID Register
*
* @return mvendorid value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MVENDORID(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mvendorid" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __get_MARCHID
*
* @brief Return Machine Architecture ID Register
*
* @return marchid value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MARCHID(void)
{
uint32_t result;
__ASM volatile("csrr %0," "marchid" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __get_MIMPID
*
* @brief Return Machine Implementation ID Register
*
* @return mimpid value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MIMPID(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mimpid" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __get_MHARTID
*
* @brief Return Hart ID Register
*
* @return mhartid value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_MHARTID(void)
{
uint32_t result;
__ASM volatile("csrr %0," "mhartid" : "=r"(result));
return (result);
}
/*********************************************************************
* @fn __get_SP
*
* @brief Return SP Register
*
* @return SP value
*/
__attribute__((always_inline)) RV_STATIC_INLINE uint32_t __get_SP(void)
{
uint32_t result;
__ASM volatile("mv %0," "sp" : "=r"(result) :);
return (result);
}
/*********************************************************************
* @fn __MCPY
*
* @brief fast memory copy asm instruction.
* @details copy memory from start to dst, copy length is (end - start).
*
*
* @return None.
*/
__attribute__((always_inline)) RV_STATIC_INLINE void __MCPY(void *dst, void *start, void *end)
{
__asm volatile("mcpy %2, %0, %1" : \
"+r"(start), "+r"(dst) : "r"(end) : "memory");
}
#define SysTick_SR_SWIE (1 << 31)
#define SysTick_SR_CNTIF (1 << 0)
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFFF)
#define SysTick_CTLR_MODE (1 << 4)
#define SysTick_CTLR_STRE (1 << 3)
#define SysTick_CTLR_STCLK (1 << 2)
#define SysTick_CTLR_STIE (1 << 1)
#define SysTick_CTLR_STE (1 << 0)
RV_STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)
return (1); /* Reload value impossible */
SysTick->CNTL = 0;
SysTick->CMP = ticks - 1; /* set reload register */
PFIC_EnableIRQ(SysTick_IRQn);
SysTick->CTLR = SysTick_CTLR_STRE |
SysTick_CTLR_STCLK |
SysTick_CTLR_STIE |
SysTick_CTLR_STE; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
RV_STATIC_INLINE uint32_t __SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)
return (1); /* Reload value impossible */
SysTick->CNTL = 0;
SysTick->CMP = ticks - 1; /* set reload register */
SysTick->CTLR = SysTick_CTLR_STRE |
SysTick_CTLR_STCLK |
SysTick_CTLR_STIE |
SysTick_CTLR_STE; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
#ifdef __cplusplus
}
#endif
#endif /* __CORE_RV3A_H__ */