637 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			637 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /********************************** (C) COPYRIGHT  *******************************
 | ||
|  |  * File Name          : core_riscv.h | ||
|  |  * Author             : WCH | ||
|  |  * Version            : V1.1.0 | ||
|  |  * Date               : 2023/04/10 | ||
|  |  * Description        : CH592 RISC-V Core Peripheral Access Layer Header File | ||
|  |  ********************************************************************************* | ||
|  |  * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. | ||
|  |  * Attention: This software (modified or not) and binary are used for  | ||
|  |  * microcontroller manufactured by Nanjing Qinheng Microelectronics. | ||
|  |  *******************************************************************************/ | ||
|  | #ifndef __CORE_RV3A_H__
 | ||
|  | #define __CORE_RV3A_H__
 | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | extern "C" { | ||
|  | #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[4];      // 44H
 | ||
|  |     __O uint32_t  CFGR;             // 48H
 | ||
|  |     __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; | ||
|  |     __IO uint64_t CNT; | ||
|  |     __IO uint64_t CMP; | ||
|  | } 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)); }) | ||
|  | 
 | ||
|  | #define PFIC_EnableAllIRQ()     {write_csr(0x800, 0x88);}
 | ||
|  | #define PFIC_DisableAllIRQ()    {write_csr(0x800, 0x80);asm volatile("fence.i");}
 | ||
|  | /* ##########################   PFIC functions  #################################### */ | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @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; | ||
|  | } | ||
|  | 
 | ||
|  | /*******************************************************************************
 | ||
|  |  * @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)); | ||
|  |     asm volatile("fence.i"); | ||
|  | } | ||
|  | 
 | ||
|  | /*******************************************************************************
 | ||
|  |  * @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-bit4:   priority | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE void PFIC_SetPriority(IRQn_Type IRQn, uint8_t priority) | ||
|  | { | ||
|  |     PFIC->IPRIOR[(uint32_t)(IRQn)] = priority; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @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->CFGR = PFIC_KEY3 | (1 << 7); | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  *  @fn      __AMOADD_W | ||
|  |  * | ||
|  |  *  @brief   Atomic Add with 32bit value | ||
|  |  *              Atomically ADD 32bit value with value in memory using amoadd.d. | ||
|  |  *              addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *                        value  value to be ADDed | ||
|  |  * | ||
|  |  * | ||
|  |  * @return  return memory value + add value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amoadd.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn      __AMOAND_W | ||
|  |  * | ||
|  |  * @brief  Atomic And with 32bit value | ||
|  |  *              Atomically AND 32bit value with value in memory using amoand.d. | ||
|  |  *              addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *              value  value to be ANDed | ||
|  |  * | ||
|  |  * | ||
|  |  * @return  return memory value & and value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amoand.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn         __AMOMAX_W | ||
|  |  * | ||
|  |  * @brief      Atomic signed MAX with 32bit value | ||
|  |  * @details   Atomically signed max compare 32bit value with value in memory using amomax.d. | ||
|  |  *                 addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *                 value  value to be compared | ||
|  |  * | ||
|  |  * | ||
|  |  * @return the bigger value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amomax.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn        __AMOMAXU_W | ||
|  |  * | ||
|  |  * @brief  Atomic unsigned MAX with 32bit value | ||
|  |  *             Atomically unsigned max compare 32bit value with value in memory using amomaxu.d. | ||
|  |  *             addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *             value  value to be compared | ||
|  |  * | ||
|  |  * @return  return the bigger value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value) | ||
|  | { | ||
|  |     uint32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amomaxu.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn      __AMOMIN_W | ||
|  |  * | ||
|  |  * @brief  Atomic signed MIN with 32bit value | ||
|  |  *             Atomically signed min compare 32bit value with value in memory using amomin.d. | ||
|  |  *             addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *             value  value to be compared | ||
|  |  * | ||
|  |  * | ||
|  |  * @return  the smaller value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amomin.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn      __AMOMINU_W | ||
|  |  * | ||
|  |  * @brief   Atomic unsigned MIN with 32bit value | ||
|  |  *              Atomically unsigned min compare 32bit value with value in memory using amominu.d. | ||
|  |  *              addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *              value  value to be compared | ||
|  |  * | ||
|  |  * | ||
|  |  * @return the smaller value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value) | ||
|  | { | ||
|  |     uint32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amominu.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn           __AMOOR_W | ||
|  |  * | ||
|  |  * @brief       Atomic OR with 32bit value | ||
|  |  * @details    Atomically OR 32bit value with value in memory using amoor.d. | ||
|  |  *                  addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *                  value  value to be ORed | ||
|  |  * | ||
|  |  * | ||
|  |  * @return  return memory value | and value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amoor.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn          __AMOSWAP_W | ||
|  |  * | ||
|  |  * @brief      Atomically swap new 32bit value into memory using amoswap.d. | ||
|  |  *                  addr      Address pointer to data, address need to be 4byte aligned | ||
|  |  *                  newval    New value to be stored into the address | ||
|  |  * | ||
|  |  * @return    return the original value in memory | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval) | ||
|  | { | ||
|  |     uint32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amoswap.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(newval) : "memory"); | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | /*********************************************************************
 | ||
|  |  * @fn        __AMOXOR_W | ||
|  |  * | ||
|  |  * @brief    Atomic XOR with 32bit value | ||
|  |  * @details Atomically XOR 32bit value with value in memory using amoxor.d. | ||
|  |  *               addr   Address pointer to data, address need to be 4byte aligned | ||
|  |  *               value  value to be XORed | ||
|  |  * | ||
|  |  * | ||
|  |  * @return  return memory value ^ and value | ||
|  |  */ | ||
|  | __attribute__((always_inline)) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value) | ||
|  | { | ||
|  |     int32_t result; | ||
|  | 
 | ||
|  |     __asm volatile ("amoxor.w %0, %2, %1" : \ | ||
|  |             "=r"(result), "+A"(*addr) : "r"(value) : "memory"); | ||
|  |     return *addr; | ||
|  | } | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine Status Register | ||
|  |  * | ||
|  |  * @return  mstatus value | ||
|  |  */ | ||
|  | uint32_t __get_MSTATUS(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine ISA Register | ||
|  |  * | ||
|  |  * @return  misa value | ||
|  |  */ | ||
|  | uint32_t __get_MISA(void); | ||
|  | 
 | ||
|  | /***
 | ||
|  |  * @brief   Return the Machine Trap-Vector Base-Address Register | ||
|  |  * | ||
|  |  * @return  mtvec value | ||
|  |  */ | ||
|  | uint32_t __get_MTVEC(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine Seratch Register | ||
|  |  * | ||
|  |  * @return  mscratch value | ||
|  |  */ | ||
|  | uint32_t __get_MSCRATCH(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine Exception Program Register | ||
|  |  * | ||
|  |  * @return  mepc value | ||
|  |  */ | ||
|  | uint32_t __get_MEPC(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine Cause Register | ||
|  |  * | ||
|  |  * @return  mcause value | ||
|  |  */ | ||
|  | uint32_t __get_MCAUSE(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return the Machine Trap Value Register | ||
|  |  * | ||
|  |  * @return  mtval value | ||
|  |  */ | ||
|  | uint32_t __get_MTVAL(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return Vendor ID Register | ||
|  |  * | ||
|  |  * @return  mvendorid value | ||
|  |  */ | ||
|  | uint32_t __get_MVENDORID(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return Machine Architecture ID Register | ||
|  |  * | ||
|  |  * @return  marchid value | ||
|  |  */ | ||
|  | uint32_t __get_MARCHID(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return Machine Implementation ID Register | ||
|  |  * | ||
|  |  * @return  mimpid value | ||
|  |  */ | ||
|  | uint32_t __get_MIMPID(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return Hart ID Register | ||
|  |  * | ||
|  |  * @return  mhartid value | ||
|  |  */ | ||
|  | uint32_t __get_MHARTID(void); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief   Return SP Register | ||
|  |  * | ||
|  |  * @return  SP value | ||
|  |  */ | ||
|  | uint32_t __get_SP(void); | ||
|  | 
 | ||
|  | #define SysTick_LOAD_RELOAD_Msk    (0xFFFFFFFFFFFFFFFF)
 | ||
|  | #define SysTick_CTLR_SWIE          (1 << 31)
 | ||
|  | #define SysTick_CTLR_INIT          (1 << 5)
 | ||
|  | #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)
 | ||
|  | 
 | ||
|  | #define SysTick_SR_CNTIF           (1 << 0)
 | ||
|  | 
 | ||
|  | RV_STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks) | ||
|  | { | ||
|  |     if((ticks - 1) > SysTick_LOAD_RELOAD_Msk) | ||
|  |         return (1); /* Reload value impossible */ | ||
|  | 
 | ||
|  |     SysTick->CMP = ticks - 1; /* set reload register */ | ||
|  |     PFIC_EnableIRQ(SysTick_IRQn); | ||
|  |     SysTick->CTLR = SysTick_CTLR_INIT | | ||
|  |                     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(uint64_t ticks) | ||
|  | { | ||
|  |     if((ticks - 1) > SysTick_LOAD_RELOAD_Msk) | ||
|  |         return (1); /* Reload value impossible */ | ||
|  | 
 | ||
|  |     SysTick->CMP = ticks - 1; /* set reload register */ | ||
|  |     SysTick->CTLR = SysTick_CTLR_INIT | | ||
|  |                     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__ */
 |