Add Nucleisys NMSIS sources

This commit is contained in:
Stefan Kerkmann 2021-03-16 19:38:46 +01:00
parent cec80982e4
commit b729125bdd
14 changed files with 23202 additions and 0 deletions

View File

@ -0,0 +1,232 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_COMPATIABLE_H__
#define __CORE_COMPATIABLE_H__
/*!
* @file core_compatiable.h
* @brief ARM compatiable function definitions header file
*/
#ifdef __cplusplus
extern "C" {
#endif
/* ===== ARM Compatiable Functions ===== */
/**
* \defgroup NMSIS_Core_ARMCompatiable_Functions ARM Compatiable Functions
* \ingroup NMSIS_Core
* \brief A few functions that compatiable with ARM CMSIS-Core.
* \details
*
* Here we provided a few functions that compatiable with ARM CMSIS-Core,
* mostly used in the DSP and NN library.
* @{
*/
/** \brief Instruction Synchronization Barrier, compatiable with ARM */
#define __ISB() __RWMB()
/** \brief Data Synchronization Barrier, compatiable with ARM */
#define __DSB() __RWMB()
/** \brief Data Memory Barrier, compatiable with ARM */
#define __DMB() __RWMB()
/** \brief LDRT Unprivileged (8 bit), ARM Compatiable */
#define __LDRBT(ptr) __LB((ptr))
/** \brief LDRT Unprivileged (16 bit), ARM Compatiable */
#define __LDRHT(ptr) __LH((ptr))
/** \brief LDRT Unprivileged (32 bit), ARM Compatiable */
#define __LDRT(ptr) __LW((ptr))
/** \brief STRT Unprivileged (8 bit), ARM Compatiable */
#define __STRBT(ptr) __SB((ptr))
/** \brief STRT Unprivileged (16 bit), ARM Compatiable */
#define __STRHT(ptr) __SH((ptr))
/** \brief STRT Unprivileged (32 bit), ARM Compatiable */
#define __STRT(ptr) __SW((ptr))
/* ===== Saturation Operations ===== */
/**
* \brief Signed Saturate
* \details Saturates a signed value.
* \param [in] value Value to be saturated
* \param [in] sat Bit position to saturate to (1..32)
* \return Saturated value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __SSAT(val, sat) __RV_SCLIP32((val), (sat-1))
#else
__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
{
if ((sat >= 1U) && (sat <= 32U)) {
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
const int32_t min = -1 - max ;
if (val > max) {
return max;
} else if (val < min) {
return min;
}
}
return val;
}
#endif
/**
* \brief Unsigned Saturate
* \details Saturates an unsigned value.
* \param [in] value Value to be saturated
* \param [in] sat Bit position to saturate to (0..31)
* \return Saturated value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __USAT(val, sat) __RV_UCLIP32((val), (sat-1))
#else
__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
{
if (sat <= 31U) {
const uint32_t max = ((1U << sat) - 1U);
if (val > (int32_t)max) {
return max;
} else if (val < 0) {
return 0U;
}
}
return (uint32_t)val;
}
#endif
/* ===== Data Processing Operations ===== */
/**
* \brief Reverse byte order (32 bit)
* \details Reverses the byte order in unsigned integer value.
* For example, 0x12345678 becomes 0x78563412.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
{
uint32_t result;
result = ((value & 0xff000000) >> 24)
| ((value & 0x00ff0000) >> 8 )
| ((value & 0x0000ff00) << 8 )
| ((value & 0x000000ff) << 24);
return result;
}
/**
* \brief Reverse byte order (16 bit)
* \details Reverses the byte order within each halfword of a word.
* For example, 0x12345678 becomes 0x34127856.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
result = ((value & 0xff000000) >> 8)
| ((value & 0x00ff00000) << 8 )
| ((value & 0x0000ff00) >> 8 )
| ((value & 0x000000ff) << 8) ;
return result;
}
/**
* \brief Reverse byte order (16 bit)
* \details Reverses the byte order in a 16-bit value
* and returns the signed 16-bit result.
* For example, 0x0080 becomes 0x8000.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
{
int16_t result;
result = ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
return result;
}
/**
* \brief Rotate Right in unsigned value (32 bit)
* \details Rotate Right (immediate) provides the value of
* the contents of a register rotated by a variable number of bits.
* \param [in] op1 Value to rotate
* \param [in] op2 Number of Bits to rotate(0-31)
* \return Rotated value
*/
__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
op2 = op2 & 0x1F;
if (op2 == 0U) {
return op1;
}
return (op1 >> op2) | (op1 << (32U - op2));
}
/**
* \brief Reverse bit order of value
* \details Reverses the bit order of the given value.
* \param [in] value Value to reverse
* \return Reversed value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __RBIT(value) __RV_BITREVI((value), 31)
#else
__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
for (value >>= 1U; value != 0U; value >>= 1U) {
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
return result;
}
#endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
/**
* \brief Count leading zeros
* \details Counts the number of leading zeros of a data value.
* \param [in] data Value to count the leading zeros
* \return number of leading zeros in value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __CLZ(data) __RV_CLZ32(data)
#else
__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t data)
{
uint8_t ret = 0;
uint32_t temp = ~data;
while (temp & 0x80000000) {
temp <<= 1;
ret++;
}
return ret;
}
#endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
/** @} */ /* End of Doxygen Group NMSIS_Core_ARMCompatiable_Functions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_COMPATIABLE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_CACHE_H__
#define __CORE_FEATURE_CACHE_H__
/*!
* @file core_feature_cache.h
* @brief Cache feature API header file for Nuclei N/NX Core
*/
/*
* Cache Feature Configuration Macro:
* 1. __ICACHE_PRESENT: Define whether I-Cache Unit is present or not.
* * 0: Not present
* * 1: Present
* 1. __DCACHE_PRESENT: Define whether D-Cache Unit is present or not.
* * 0: Not present
* * 1: Present
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1)
/* ########################## Cache functions #################################### */
/**
* \defgroup NMSIS_Core_Cache Cache Functions
* \brief Functions that configure Instruction and Data Cache.
* @{
*/
/** @} */ /* End of Doxygen Group NMSIS_Core_Cache */
/**
* \defgroup NMSIS_Core_ICache I-Cache Functions
* \ingroup NMSIS_Core_Cache
* \brief Functions that configure Instruction Cache.
* @{
*/
/**
* \brief Enable ICache
* \details
* This function enable I-Cache
* \remarks
* - This \ref CSR_MCACHE_CTL register control I Cache enable.
* \sa
* - \ref DisableICache
*/
__STATIC_FORCEINLINE void EnableICache (void)
{
__RV_CSR_SET(CSR_MCACHE_CTL, CSR_MCACHE_CTL_IE);
}
/**
* \brief Disable ICache
* \details
* This function Disable I-Cache
* \remarks
* - This \ref CSR_MCACHE_CTL register control I Cache enable.
* \sa
* - \ref EnableICache
*/
__STATIC_FORCEINLINE void DisableICache (void)
{
__RV_CSR_CLEAR(CSR_MCACHE_CTL, CSR_MCACHE_CTL_IE);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_ICache */
#endif /* defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1) */
#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1)
/**
* \defgroup NMSIS_Core_DCache D-Cache Functions
* \ingroup NMSIS_Core_Cache
* \brief Functions that configure Data Cache.
* @{
*/
/**
* \brief Enable DCache
* \details
* This function enable D-Cache
* \remarks
* - This \ref CSR_MCACHE_CTL register control D Cache enable.
* \sa
* - \ref DisableDCache
*/
__STATIC_FORCEINLINE void EnableDCache (void)
{
__RV_CSR_SET(CSR_MCACHE_CTL, CSR_MCACHE_CTL_DE);
}
/**
* \brief Disable DCache
* \details
* This function Disable D-Cache
* \remarks
* - This \ref CSR_MCACHE_CTL register control D Cache enable.
* \sa
* - \ref EnableDCache
*/
__STATIC_FORCEINLINE void DisableDCache (void)
{
__RV_CSR_CLEAR(CSR_MCACHE_CTL, CSR_MCACHE_CTL_DE);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_DCache */
#endif /* defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /** __CORE_FEATURE_CACHE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,897 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_ECLIC__
#define __CORE_FEATURE_ECLIC__
/*!
* @file core_feature_eclic.h
* @brief ECLIC feature API header file for Nuclei N/NX Core
*/
/*
* ECLIC Feature Configuration Macro:
* 1. __ECLIC_PRESENT: Define whether Enhanced Core Local Interrupt Controller (ECLIC) Unit is present or not
* * 0: Not present
* * 1: Present
* 2. __ECLIC_BASEADDR: Base address of the ECLIC unit.
* 3. ECLIC_GetInfoCtlbits(): Define the number of hardware bits are actually implemented in the clicintctl registers.
* Valid number is 1 - 8.
* 4. __ECLIC_INTNUM : Define the external interrupt number of ECLIC Unit
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* \defgroup NMSIS_Core_ECLIC_Registers Register Define and Type Definitions Of ECLIC
* \ingroup NMSIS_Core_Registers
* \brief Type definitions and defines for eclic registers.
*
* @{
*/
/**
* \brief Union type to access CLICFG configure register.
*/
typedef union
{
struct {
uint8_t _reserved0:1; /*!< bit: 0 Overflow condition code flag */
uint8_t nlbits:4; /*!< bit: 29 Carry condition code flag */
uint8_t _reserved1:2; /*!< bit: 30 Zero condition code flag */
uint8_t _reserved2:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint8_t w; /*!< Type used for byte access */
} CLICCFG_Type;
/**
* \brief Union type to access CLICINFO information register.
*/
typedef union {
struct {
uint32_t numint:13; /*!< bit: 0..12 number of maximum interrupt inputs supported */
uint32_t version:8; /*!< bit: 13..20 20:17 for architecture version,16:13 for implementation version */
uint32_t intctlbits:4; /*!< bit: 21..24 specifies how many hardware bits are actually implemented in the clicintctl registers */
uint32_t _reserved0:8; /*!< bit: 25..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CLICINFO_Type;
/**
* \brief Access to the structure of a vector interrupt controller.
*/
typedef struct {
__IOM uint8_t INTIP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */
__IOM uint8_t INTIE; /*!< Offset: 0x001 (R/W) Interrupt set enable register */
__IOM uint8_t INTATTR; /*!< Offset: 0x002 (R/W) Interrupt set attributes register */
__IOM uint8_t INTCTRL; /*!< Offset: 0x003 (R/W) Interrupt configure register */
} CLIC_CTRL_Type;
typedef struct {
__IOM uint8_t CFG; /*!< Offset: 0x000 (R/W) CLIC configuration register */
uint8_t RESERVED0[3];
__IM uint32_t INFO; /*!< Offset: 0x004 (R/ ) CLIC information register */
uint8_t RESERVED1[3];
__IOM uint8_t MTH; /*!< Offset: 0x00B (R/W) CLIC machine mode threshold register */
uint32_t RESERVED2[0x3FD];
CLIC_CTRL_Type CTRL[4096]; /*!< Offset: 0x1000 (R/W) CLIC register structure for INTIP, INTIE, INTATTR, INTCTL */
} CLIC_Type;
#define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */
#define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */
#define CLIC_CLICINFO_CTLBIT_Pos 21U /*!< CLIC INTINFO: __ECLIC_GetInfoCtlbits() Position */
#define CLIC_CLICINFO_CTLBIT_Msk (0xFUL << CLIC_CLICINFO_CTLBIT_Pos) /*!< CLIC INTINFO: __ECLIC_GetInfoCtlbits() Mask */
#define CLIC_CLICINFO_VER_Pos 13U /*!< CLIC CLICINFO: VERSION Position */
#define CLIC_CLICINFO_VER_Msk (0xFFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICINFO: VERSION Mask */
#define CLIC_CLICINFO_NUM_Pos 0U /*!< CLIC CLICINFO: NUM Position */
#define CLIC_CLICINFO_NUM_Msk (0xFFFUL << CLIC_CLICINFO_NUM_Pos) /*!< CLIC CLICINFO: NUM Mask */
#define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */
#define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */
#define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */
#define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */
#define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */
#define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */
#define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */
#define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */
#define ECLIC_MAX_NLBITS 8U /*!< Max nlbit of the CLICINTCTLBITS */
#define ECLIC_MODE_MTVEC_Msk 3U /*!< ECLIC Mode mask for MTVT CSR Register */
#define ECLIC_NON_VECTOR_INTERRUPT 0x0 /*!< Non-Vector Interrupt Mode of ECLIC */
#define ECLIC_VECTOR_INTERRUPT 0x1 /*!< Vector Interrupt Mode of ECLIC */
/**\brief ECLIC Trigger Enum for different Trigger Type */
typedef enum ECLIC_TRIGGER {
ECLIC_LEVEL_TRIGGER = 0x0, /*!< Level Triggerred, trig[0] = 0 */
ECLIC_POSTIVE_EDGE_TRIGGER = 0x1, /*!< Postive/Rising Edge Triggered, trig[1] = 1, trig[0] = 0 */
ECLIC_NEGTIVE_EDGE_TRIGGER = 0x3, /*!< Negtive/Falling Edge Triggered, trig[1] = 1, trig[0] = 0 */
ECLIC_MAX_TRIGGER = 0x3 /*!< MAX Supported Trigger Mode */
} ECLIC_TRIGGER_Type;
#ifndef __ECLIC_BASEADDR
/* Base address of ECLIC(__ECLIC_BASEADDR) should be defined in <Device.h> */
#error "__ECLIC_BASEADDR is not defined, please check!"
#endif
#ifndef __ECLIC_INTCTLBITS
/* Define __ECLIC_INTCTLBITS to get via ECLIC->INFO if not defined */
#define __ECLIC_INTCTLBITS (__ECLIC_GetInfoCtlbits())
#endif
/* ECLIC Memory mapping of Device */
#define ECLIC_BASE __ECLIC_BASEADDR /*!< ECLIC Base Address */
#define ECLIC ((CLIC_Type *) ECLIC_BASE) /*!< CLIC configuration struct */
/** @} */ /* end of group NMSIS_Core_ECLIC_Registers */
/* ########################## ECLIC functions #################################### */
/**
* \defgroup NMSIS_Core_IntExc Interrupts and Exceptions
* \brief Functions that manage interrupts and exceptions via the ECLIC.
*
* @{
*/
/**
* \brief Definition of IRQn numbers
* \details
* The core interrupt enumeration names for IRQn values are defined in the file <b><Device>.h</b>.
* - 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.
*/
/* The following enum IRQn definition in this file
* is only used for doxygen documentation generation,
* The <Device>.h is the real file to define it by vendor
*/
#if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
typedef enum IRQn {
/* ========= Nuclei N/NX Core Specific Interrupt Numbers =========== */
/* Core Internal Interrupt IRQn definitions */
Reserved0_IRQn = 0, /*!< Internal reserved */
Reserved1_IRQn = 1, /*!< Internal reserved */
Reserved2_IRQn = 2, /*!< Internal reserved */
SysTimerSW_IRQn = 3, /*!< System Timer SW interrupt */
Reserved3_IRQn = 4, /*!< Internal reserved */
Reserved4_IRQn = 5, /*!< Internal reserved */
Reserved5_IRQn = 6, /*!< Internal reserved */
SysTimer_IRQn = 7, /*!< System Timer Interrupt */
Reserved6_IRQn = 8, /*!< Internal reserved */
Reserved7_IRQn = 9, /*!< Internal reserved */
Reserved8_IRQn = 10, /*!< Internal reserved */
Reserved9_IRQn = 11, /*!< Internal reserved */
Reserved10_IRQn = 12, /*!< Internal reserved */
Reserved11_IRQn = 13, /*!< Internal reserved */
Reserved12_IRQn = 14, /*!< Internal reserved */
Reserved13_IRQn = 15, /*!< Internal reserved */
Reserved14_IRQn = 16, /*!< Internal reserved */
Reserved15_IRQn = 17, /*!< Internal reserved */
Reserved16_IRQn = 18, /*!< Internal reserved */
/* ========= Device Specific Interrupt Numbers =================== */
/* ToDo: add here your device specific external interrupt numbers.
* 19~max(NUM_INTERRUPT, 1023) is reserved number for user.
* Maxmum interrupt supported could get from clicinfo.NUM_INTERRUPT.
* According the interrupt handlers defined in startup_Device.S
* eg.: Interrupt for Timer#1 eclic_tim1_handler -> TIM1_IRQn */
FirstDeviceSpecificInterrupt_IRQn = 19, /*!< First Device Specific Interrupt */
SOC_INT_MAX, /*!< Number of total interrupts */
} IRQn_Type;
#endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
#ifdef NMSIS_ECLIC_VIRTUAL
#ifndef NMSIS_ECLIC_VIRTUAL_HEADER_FILE
#define NMSIS_ECLIC_VIRTUAL_HEADER_FILE "nmsis_eclic_virtual.h"
#endif
#include NMSIS_ECLIC_VIRTUAL_HEADER_FILE
#else
#define ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
#define ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
#define ECLIC_GetInfoVer __ECLIC_GetInfoVer
#define ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
#define ECLIC_GetInfoNum __ECLIC_GetInfoNum
#define ECLIC_SetMth __ECLIC_SetMth
#define ECLIC_GetMth __ECLIC_GetMth
#define ECLIC_EnableIRQ __ECLIC_EnableIRQ
#define ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
#define ECLIC_DisableIRQ __ECLIC_DisableIRQ
#define ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
#define ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
#define ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
#define ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
#define ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
#define ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
#define ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
#define ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
#define ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
#define ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
#define ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
#define ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
#define ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
#endif /* NMSIS_ECLIC_VIRTUAL */
#ifdef NMSIS_VECTAB_VIRTUAL
#ifndef NMSIS_VECTAB_VIRTUAL_HEADER_FILE
#define NMSIS_VECTAB_VIRTUAL_HEADER_FILE "nmsis_vectab_virtual.h"
#endif
#include NMSIS_VECTAB_VIRTUAL_HEADER_FILE
#else
#define ECLIC_SetVector __ECLIC_SetVector
#define ECLIC_GetVector __ECLIC_GetVector
#endif /* (NMSIS_VECTAB_VIRTUAL) */
/**
* \brief Set nlbits value
* \details
* This function set the nlbits value of CLICCFG register.
* \param [in] nlbits nlbits value
* \remarks
* - nlbits is used to set the width of level in the CLICINTCTL[i].
* \sa
* - \ref ECLIC_GetCfgNlbits
*/
__STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits(uint32_t nlbits)
{
ECLIC->CFG &= ~CLIC_CLICCFG_NLBIT_Msk;
ECLIC->CFG |= (uint8_t)((nlbits <<CLIC_CLICCFG_NLBIT_Pos) & CLIC_CLICCFG_NLBIT_Msk);
}
/**
* \brief Get nlbits value
* \details
* This function get the nlbits value of CLICCFG register.
* \return nlbits value of CLICCFG register
* \remarks
* - nlbits is used to set the width of level in the CLICINTCTL[i].
* \sa
* - \ref ECLIC_SetCfgNlbits
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits(void)
{
return ((uint32_t)((ECLIC->CFG & CLIC_CLICCFG_NLBIT_Msk) >> CLIC_CLICCFG_NLBIT_Pos));
}
/**
* \brief Get the ECLIC version number
* \details
* This function gets the hardware version information from CLICINFO register.
* \return hardware version number in CLICINFO register.
* \remarks
* - This function gets harware version information from CLICINFO register.
* - Bit 20:17 for architecture version, bit 16:13 for implementation version.
* \sa
* - \ref ECLIC_GetInfoNum
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer(void)
{
return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_VER_Msk) >> CLIC_CLICINFO_VER_Pos));
}
/**
* \brief Get CLICINTCTLBITS
* \details
* This function gets CLICINTCTLBITS from CLICINFO register.
* \return CLICINTCTLBITS from CLICINFO register.
* \remarks
* - 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.
* \sa
* - \ref ECLIC_GetInfoNum
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits(void)
{
return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_CTLBIT_Msk) >> CLIC_CLICINFO_CTLBIT_Pos));
}
/**
* \brief Get number of maximum interrupt inputs supported
* \details
* This function gets number of maximum interrupt inputs supported from CLICINFO register.
* \return number of maximum interrupt inputs supported from CLICINFO register.
* \remarks
* - 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.
* \sa
* - \ref ECLIC_GetInfoCtlbits
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum(void)
{
return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_NUM_Msk) >> CLIC_CLICINFO_NUM_Pos));
}
/**
* \brief Set Machine Mode Interrupt Level Threshold
* \details
* This function sets machine mode interrupt level threshold.
* \param [in] mth Interrupt Level Threshold.
* \sa
* - \ref ECLIC_GetMth
*/
__STATIC_FORCEINLINE void __ECLIC_SetMth(uint8_t mth)
{
ECLIC->MTH = mth;
}
/**
* \brief Get Machine Mode Interrupt Level Threshold
* \details
* This function gets machine mode interrupt level threshold.
* \return Interrupt Level Threshold.
* \sa
* - \ref ECLIC_SetMth
*/
__STATIC_FORCEINLINE uint8_t __ECLIC_GetMth(void)
{
return (ECLIC->MTH);
}
/**
* \brief Enable a specific interrupt
* \details
* This function enables the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_DisableIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_EnableIRQ(IRQn_Type IRQn)
{
ECLIC->CTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
}
/**
* \brief Get a specific interrupt enable status
* \details
* This function returns the interrupt enable status for the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \returns
* - 0 Interrupt is not enabled
* - 1 Interrupt is pending
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_EnableIRQ
* - \ref ECLIC_DisableIRQ
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ(IRQn_Type IRQn)
{
return((uint32_t) (ECLIC->CTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
}
/**
* \brief Disable a specific interrupt
* \details
* This function disables the specific interrupt \em IRQn.
* \param [in] IRQn Number of the external interrupt to disable
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_EnableIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_DisableIRQ(IRQn_Type IRQn)
{
ECLIC->CTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
}
/**
* \brief Get the pending specific interrupt
* \details
* This function returns the pending status of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \returns
* - 0 Interrupt is not pending
* - 1 Interrupt is pending
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetPendingIRQ
* - \ref ECLIC_ClearPendingIRQ
*/
__STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t)(ECLIC->CTRL[IRQn].INTIP) & CLIC_INTIP_IP_Msk);
}
/**
* \brief Set a specific interrupt to pending
* \details
* This function sets the pending bit for the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_GetPendingIRQ
* - \ref ECLIC_ClearPendingIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ(IRQn_Type IRQn)
{
ECLIC->CTRL[IRQn].INTIP |= CLIC_INTIP_IP_Msk;
}
/**
* \brief Clear a specific interrupt from pending
* \details
* This function removes the pending state of the specific interrupt \em IRQn.
* \em IRQn cannot be a negative number.
* \param [in] IRQn Interrupt number
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetPendingIRQ
* - \ref ECLIC_GetPendingIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ(IRQn_Type IRQn)
{
ECLIC->CTRL[IRQn].INTIP &= ~ CLIC_INTIP_IP_Msk;
}
/**
* \brief Set trigger mode and polarity for a specific interrupt
* \details
* This function set trigger mode and polarity of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] trig
* - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
* - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
* - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
* - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
* \remarks
* - IRQn must not be negative.
*
* \sa
* - \ref ECLIC_GetTrigIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ(IRQn_Type IRQn, uint32_t trig)
{
ECLIC->CTRL[IRQn].INTATTR &= ~CLIC_INTATTR_TRIG_Msk;
ECLIC->CTRL[IRQn].INTATTR |= (uint8_t)(trig<<CLIC_INTATTR_TRIG_Pos);
}
/**
* \brief Get trigger mode and polarity for a specific interrupt
* \details
* This function get trigger mode and polarity of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return
* - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
* - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
* - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
* - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetTrigIRQ
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ(IRQn_Type IRQn)
{
return ((int32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk)>>CLIC_INTATTR_TRIG_Pos));
}
/**
* \brief Set interrupt working mode for a specific interrupt
* \details
* This function set selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] shv
* - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
* - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_GetShvIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ(IRQn_Type IRQn, uint32_t shv)
{
ECLIC->CTRL[IRQn].INTATTR &= ~CLIC_INTATTR_SHV_Msk;
ECLIC->CTRL[IRQn].INTATTR |= (uint8_t)(shv<<CLIC_INTATTR_SHV_Pos);
}
/**
* \brief Get interrupt working mode for a specific interrupt
* \details
* This function get selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return shv
* - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
* - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetShvIRQ
*/
__STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ(IRQn_Type IRQn)
{
return ((int32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk)>>CLIC_INTATTR_SHV_Pos));
}
/**
* \brief Modify ECLIC Interrupt Input Control Register for a specific interrupt
* \details
* This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] intctrl Set value for CLICINTCTL[i] register
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_GetCtrlIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ(IRQn_Type IRQn, uint8_t intctrl)
{
ECLIC->CTRL[IRQn].INTCTRL = intctrl;
}
/**
* \brief Get ECLIC Interrupt Input Control Register value for a specific interrupt
* \details
* This function modify ECLIC Interrupt Input Control register of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return value of ECLIC Interrupt Input Control register
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetCtrlIRQ
*/
__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ(IRQn_Type IRQn)
{
return (ECLIC->CTRL[IRQn].INTCTRL);
}
/**
* \brief Set ECLIC Interrupt level of a specific interrupt
* \details
* This function set interrupt level of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] lvl_abs Interrupt level
* \remarks
* - 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.
* \sa
* - \ref ECLIC_GetLevelIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ(IRQn_Type IRQn, uint8_t lvl_abs)
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
if (nlbits == 0) {
return;
}
if (nlbits > intctlbits) {
nlbits = intctlbits;
}
uint8_t maxlvl = ((1 << nlbits) - 1);
if (lvl_abs > maxlvl) {
lvl_abs = maxlvl;
}
uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
cur_ctrl = cur_ctrl << nlbits;
cur_ctrl = cur_ctrl >> nlbits;
__ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | lvl));
}
/**
* \brief Get ECLIC Interrupt level of a specific interrupt
* \details
* This function get interrupt level of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return Interrupt level
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetLevelIRQ
*/
__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ(IRQn_Type IRQn)
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
if (nlbits == 0) {
return 0;
}
if (nlbits > intctlbits) {
nlbits = intctlbits;
}
uint8_t intctrl = __ECLIC_GetCtrlIRQ(IRQn);
uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
return lvl_abs;
}
/**
* \brief Get ECLIC Interrupt priority of a specific interrupt
* \details
* This function get interrupt priority of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] pri Interrupt priority
* \remarks
* - 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.
* \sa
* - \ref ECLIC_GetPriorityIRQ
*/
__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ(IRQn_Type IRQn, uint8_t pri)
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
if (nlbits < intctlbits) {
uint8_t maxpri = ((1 << (intctlbits - nlbits)) - 1);
if (pri > maxpri) {
pri = maxpri;
}
pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
pri = pri | mask;
uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
__ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | pri));
}
}
/**
* \brief Get ECLIC Interrupt priority of a specific interrupt
* \details
* This function get interrupt priority of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return Interrupt priority
* \remarks
* - IRQn must not be negative.
* \sa
* - \ref ECLIC_SetPriorityIRQ
*/
__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ(IRQn_Type IRQn)
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
if (nlbits < intctlbits) {
uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
uint8_t pri = cur_ctrl << nlbits;
pri = pri >> nlbits;
pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
return pri;
} else {
return 0;
}
}
/**
* \brief Set Interrupt Vector of a specific interrupt
* \details
* This function set interrupt handler address of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \param [in] vector Interrupt handler address
* \remarks
* - IRQn must not be negative.
* - You can set the \ref 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.
* \sa
* - \ref ECLIC_GetVector
*/
__STATIC_FORCEINLINE void __ECLIC_SetVector(IRQn_Type IRQn, rv_csr_t vector)
{
#if __RISCV_XLEN == 32
volatile uint32_t vec_base;
vec_base = ((uint32_t)__RV_CSR_READ(CSR_MTVT));
(* (unsigned long *) (vec_base + ((int32_t)IRQn) * 4)) = vector;
#elif __RISCV_XLEN == 64
volatile uint64_t vec_base;
vec_base = ((uint64_t)__RV_CSR_READ(CSR_MTVT));
(* (unsigned long *) (vec_base + ((int32_t)IRQn) * 8)) = vector;
#else // TODO Need cover for XLEN=128 case in future
volatile uint64_t vec_base;
vec_base = ((uint64_t)__RV_CSR_READ(CSR_MTVT));
(* (unsigned long *) (vec_base + ((int32_t)IRQn) * 8)) = vector;
#endif
}
/**
* \brief Get Interrupt Vector of a specific interrupt
* \details
* This function get interrupt handler address of the specific interrupt \em IRQn.
* \param [in] IRQn Interrupt number
* \return Interrupt handler address
* \remarks
* - IRQn must not be negative.
* - You can read \ref CSR_CSR_MTVT to get interrupt vector table entry address.
* \sa
* - \ref ECLIC_SetVector
*/
__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector(IRQn_Type IRQn)
{
#if __RISCV_XLEN == 32
return (*(uint32_t *)(__RV_CSR_READ(CSR_MTVT)+IRQn*4));
#elif __RISCV_XLEN == 64
return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT)+IRQn*8));
#else // TODO Need cover for XLEN=128 case in future
return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT)+IRQn*8));
#endif
}
/**
* \brief Set Exception entry address
* \details
* This function set exception handler address to 'CSR_MTVEC'.
* \param [in] addr Exception handler address
* \remarks
* - This function use to set exception handler address to 'CSR_MTVEC'. Address is 4 bytes align.
* \sa
* - \ref __get_exc_entry
*/
__STATIC_FORCEINLINE void __set_exc_entry(rv_csr_t addr)
{
addr &= (rv_csr_t)(~0x3F);
addr |= ECLIC_MODE_MTVEC_Msk;
__RV_CSR_WRITE(CSR_MTVEC, addr);
}
/**
* \brief Get Exception entry address
* \details
* This function get exception handler address from 'CSR_MTVEC'.
* \return Exception handler address
* \remarks
* - This function use to get exception handler address from 'CSR_MTVEC'. Address is 4 bytes align
* \sa
* - \ref __set_exc_entry
*/
__STATIC_FORCEINLINE rv_csr_t __get_exc_entry(void)
{
unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
return (addr & ~ECLIC_MODE_MTVEC_Msk);
}
/**
* \brief Set Non-vector interrupt entry address
* \details
* This function set Non-vector interrupt address.
* \param [in] addr Non-vector interrupt entry address
* \remarks
* - 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'
* \sa
* - \ref __get_nonvec_entry
*/
__STATIC_FORCEINLINE void __set_nonvec_entry(rv_csr_t addr)
{
if (__RV_CSR_READ(CSR_MTVT2) & 0x1){
__RV_CSR_WRITE(CSR_MTVT2, addr | 0x01);
} else {
addr &= (rv_csr_t)(~0x3F);
addr |= ECLIC_MODE_MTVEC_Msk;
__RV_CSR_WRITE(CSR_MTVEC, addr);
}
}
/**
* \brief Get Non-vector interrupt entry address
* \details
* This function get Non-vector interrupt address.
* \return Non-vector interrupt handler address
* \remarks
* - 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'.
* \sa
* - \ref __set_nonvec_entry
*/
__STATIC_FORCEINLINE rv_csr_t __get_nonvec_entry(void)
{
if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
return __RV_CSR_READ(CSR_MTVT2) & (~(rv_csr_t)(0x1));
} else {
rv_csr_t addr = __RV_CSR_READ(CSR_MTVEC);
return (addr & ~ECLIC_MODE_MTVEC_Msk);
}
}
/**
* \brief Get NMI interrupt entry from 'CSR_MNVEC'
* \details
* This function get NMI interrupt address from 'CSR_MNVEC'.
* \return NMI interrupt handler address
* \remarks
* - 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 \ref CSR_MMISC_CTL, writing to \ref CSR_MNVEC will be ignored.
*/
__STATIC_FORCEINLINE rv_csr_t __get_nmi_entry(void)
{
return __RV_CSR_READ(CSR_MNVEC);
}
/**
* \brief Save necessary CSRs into variables for vector interrupt nesting
* \details
* 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.
* \remarks
* - Interrupt will be enabled after this macro is called
* - It need to be used together with \ref 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:
* \code
* // __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();
* }
* \endcode
*/
#define SAVE_IRQ_CSR_CONTEXT() \
rv_csr_t __mcause = __RV_CSR_READ(CSR_MCAUSE); \
rv_csr_t __mepc = __RV_CSR_READ(CSR_MEPC); \
rv_csr_t __msubm = __RV_CSR_READ(CSR_MSUBM); \
__enable_irq();
/**
* \brief Restore necessary CSRs from variables for vector interrupt nesting
* \details
* This macro is used restore CSRs(MCAUSE, MEPC, MSUB) from pre-defined variables
* in \ref SAVE_IRQ_CSR_CONTEXT macro.
* \remarks
* - Interrupt will be disabled after this macro is called
* - It need to be used together with \ref SAVE_IRQ_CSR_CONTEXT
*/
#define RESTORE_IRQ_CSR_CONTEXT() \
__disable_irq(); \
__RV_CSR_WRITE(CSR_MSUBM, __msubm); \
__RV_CSR_WRITE(CSR_MEPC, __mepc); \
__RV_CSR_WRITE(CSR_MCAUSE, __mcause);
/** @} */ /* End of Doxygen Group NMSIS_Core_IntExc */
#endif /* defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /** __CORE_FEATURE_ECLIC__ */

View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_FPU_H__
#define __CORE_FEATURE_FPU_H__
/*!
* @file core_feature_fpu.h
* @brief FPU feature API header file for Nuclei N/NX Core
*/
/*
* FPU Feature Configuration Macro:
* 1. __FPU_PRESENT: Define whether Floating Point Unit(FPU) is present or not
* * 0: Not present
* * 1: Single precision FPU present, __RISCV_FLEN == 32
* * 2: Double precision FPU present, __RISCV_FLEN == 64
*/
#ifdef __cplusplus
extern "C" {
#endif
/* ===== FPU Operations ===== */
/**
* \defgroup NMSIS_Core_FPU_Functions FPU Functions
* \ingroup NMSIS_Core
* \brief Functions that related to the RISC-V FPU (F and D extension).
* \details
*
* Nuclei provided floating point unit by RISC-V F and D extension.
* * `F extension` adds single-precision floating-point computational
* instructions compliant with the IEEE 754-2008 arithmetic standard, __RISCV_FLEN = 32.
* The F extension adds 32 floating-point registers, f0-f31, each 32 bits wide,
* and a floating-point control and status register fcsr, which contains the
* operating mode and exception status of the floating-point unit.
* * `D extension` adds double-precision floating-point computational instructions
* compliant with the IEEE 754-2008 arithmetic standard.
* The D extension widens the 32 floating-point registers, f0-f31, to 64 bits, __RISCV_FLEN = 64
* @{
*/
#if defined(__FPU_PRESENT) && (__FPU_PRESENT > 0)
#if __FPU_PRESENT == 1
/** \brief Refer to the width of the floating point register in bits(either 32 or 64) */
#define __RISCV_FLEN 32
#elif __FPU_PRESENT == 2
#define __RISCV_FLEN 64
#else
#define __RISCV_FLEN __riscv_flen
#endif /* __FPU_PRESENT == 1 */
/** \brief Get FCSR CSR Register */
#define __get_FCSR() __RV_CSR_READ(CSR_FCSR)
/** \brief Set FCSR CSR Register with val */
#define __set_FCSR(val) __RV_CSR_WRITE(CSR_FCSR, (val))
/** \brief Get FRM CSR Register */
#define __get_FRM() __RV_CSR_READ(CSR_FRM)
/** \brief Set FRM CSR Register with val */
#define __set_FRM(val) __RV_CSR_WRITE(CSR_FRM, (val))
/** \brief Get FFLAGS CSR Register */
#define __get_FFLAGS() __RV_CSR_READ(CSR_FFLAGS)
/** \brief Set FFLAGS CSR Register with val */
#define __set_FFLAGS(val) __RV_CSR_WRITE(CSR_FFLAGS, (val))
/** \brief Enable FPU Unit */
#define __enable_FPU() __RV_CSR_SET(CSR_MSTATUS, MSTATUS_FS)
/**
* \brief Disable FPU Unit
* \details
* * We can save power by disable FPU Unit.
* * When FPU Unit is disabled, any access to FPU related CSR registers
* and FPU instructions will cause illegal Instuction Exception.
* */
#define __disable_FPU() __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS)
/**
* \brief Load a single-precision value from memory into float point register freg using flw instruction
* \details The FLW instruction loads a single-precision floating point value from memory
* address (addr + ofs) into floating point register freg(f0-f31)
* \param [in] freg The floating point register, eg. FREG(0), f0
* \param [in] addr The memory base address, 4 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \remarks
* * FLW and FSW operations need to make sure the address is 4 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved
*
*/
#define __RV_FLW(freg, addr, ofs) \
({ \
register rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("flw " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Store a single-precision value from float point freg into memory using fsw instruction
* \details The FSW instruction stores a single-precision value from floating point register to memory
* \param [in] freg The floating point register(f0-f31), eg. FREG(0), f0
* \param [in] addr The memory base address, 4 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \remarks
* * FLW and FSW operations need to make sure the address is 4 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved
*
*/
#define __RV_FSW(freg, addr, ofs) \
({ \
register rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fsw " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Load a double-precision value from memory into float point register freg using fld instruction
* \details The FLD instruction loads a double-precision floating point value from memory
* address (addr + ofs) into floating point register freg(f0-f31)
* \param [in] freg The floating point register, eg. FREG(0), f0
* \param [in] addr The memory base address, 8 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \attention
* * Function only available for double precision floating point unit, FLEN = 64
* \remarks
* * FLD and FSD operations need to make sure the address is 8 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved.
*/
#define __RV_FLD(freg, addr, ofs) \
({ \
register rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fld " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Store a double-precision value from float point freg into memory using fsd instruction
* \details The FSD instruction stores double-precision value from floating point register to memory
* \param [in] freg The floating point register(f0-f31), eg. FREG(0), f0
* \param [in] addr The memory base address, 8 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \attention
* * Function only available for double precision floating point unit, FLEN = 64
* \remarks
* * FLD and FSD operations need to make sure the address is 8 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved.
*
*/
#define __RV_FSD(freg, addr, ofs) \
({ \
register rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fsd " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \def __RV_FLOAD
* \brief Load a float point value from memory into float point register freg using flw/fld instruction
* \details
* * For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32):
* It will call \ref __RV_FLW to load a single-precision floating point value from memory to floating point register
* * For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64):
* It will call \ref __RV_FLD to load a double-precision floating point value from memory to floating point register
*
* \attention
* Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent
*/
/**
* \def __RV_FSTORE
* \brief Store a float value from float point freg into memory using fsw/fsd instruction
* \details
* * For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32):
* It will call \ref __RV_FSW to store floating point register into memory
* * For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64):
* It will call \ref __RV_FSD to store floating point register into memory
*
* \attention
* Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent
*/
#if __FPU_PRESENT == 1
#define __RV_FLOAD __RV_FLW
#define __RV_FSTORE __RV_FSW
/** \brief Type of FPU register, depends on the FLEN defined in RISC-V */
typedef uint32_t rv_fpu_t;
#elif __FPU_PRESENT == 2
#define __RV_FLOAD __RV_FLD
#define __RV_FSTORE __RV_FSD
/** \brief Type of FPU register, depends on the FLEN defined in RISC-V */
typedef uint64_t rv_fpu_t;
#endif /* __FPU_PRESENT == 2 */
/**
* \brief Save FPU context into variables for interrupt nesting
* \details
* This macro is used to declare variables which are used for saving
* FPU context, and it will store the nessary fpu registers into
* these variables, it need to be used in a interrupt when in this
* interrupt fpu registers are used.
* \remarks
* - It need to be used together with \ref RESTORE_FPU_CONTEXT
* - Don't use variable names __fpu_context in your ISR code
* - If you isr code will use fpu registers, and this interrupt is nested.
* Then you can do it like this:
* \code
* void eclic_mtip_handler(void)
* {
* // !!!Interrupt is enabled here!!!
* // !!!Higher priority interrupt could nest it!!!
*
* // Necessary only when you need to use fpu registers
* // in this isr handler functions
* SAVE_FPU_CONTEXT();
*
* // put you own interrupt handling code here
*
* // pair of SAVE_FPU_CONTEXT()
* RESTORE_FPU_CONTEXT();
* }
* \endcode
*/
#define SAVE_FPU_CONTEXT() \
rv_fpu_t __fpu_context[20]; \
__RV_FSTORE(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
/**
* \brief Restore necessary fpu registers from variables for interrupt nesting
* \details
* This macro is used restore necessary fpu registers from pre-defined variables
* in \ref SAVE_FPU_CONTEXT macro.
* \remarks
* - It need to be used together with \ref SAVE_FPU_CONTEXT
*/
#define RESTORE_FPU_CONTEXT() \
__RV_FLOAD(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
#else
#define SAVE_FPU_CONTEXT()
#define RESTORE_FPU_CONTEXT()
#endif /* __FPU_PRESENT > 0 */
/** @} */ /* End of Doxygen Group NMSIS_Core_FPU_Functions */
#ifdef __cplusplus
}
#endif
#endif /** __RISCV_EXT_FPU_H__ */

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_PMP_H__
#define __CORE_FEATURE_PMP_H__
/*!
* @file core_feature_pmp.h
* @brief PMP feature API header file for Nuclei N/NX Core
*/
/*
* PMP Feature Configuration Macro:
* 1. __PMP_PRESENT: Define whether Physical Memory Protection(PMP) is present or not
* * 0: Not present
* * 1: Present
* 2. __PMP_ENTRY_NUM: Define the number of PMP entries, only 8 or 16 is configurable.
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__PMP_PRESENT) && (__PMP_PRESENT == 1)
/* ===== PMP Operations ===== */
/**
* \defgroup NMSIS_Core_PMP_Functions PMP Functions
* \ingroup NMSIS_Core
* \brief Functions that related to the RISCV Phyiscal Memory Protection.
* \details
* Optional physical memory protection (PMP) unit provides per-hart machine-mode
* control registers to allow physical memory access privileges (read, write, execute)
* to be specified for each physical memory region.
*
* The PMP can supports region access control settings as small as four bytes.
*
* @{
*/
#ifndef __PMP_ENTRY_NUM
/* numbers of PMP entries(__PMP_ENTRY_NUM) should be defined in <Device.h> */
#error "__PMP_ENTRY_NUM is not defined, please check!"
#endif
/**
* \brief Get 8bit PMPxCFG Register by PMP entry index
* \details Return the content of the PMPxCFG Register.
* \param [in] idx PMP region index(0-15)
* \return PMPxCFG Register value
*/
__STATIC_INLINE uint8_t __get_PMPxCFG(uint32_t idx)
{
rv_csr_t pmpcfg = 0;
if (idx >= __PMP_ENTRY_NUM) return 0;
#if __RISCV_XLEN == 32
if (idx < 4) {
pmpcfg = __RV_CSR_READ(CSR_PMPCFG0);
} else if ((idx >=4) && (idx < 8)) {
idx -= 4;
pmpcfg = __RV_CSR_READ(CSR_PMPCFG1);
} else if ((idx >=8) && (idx < 12)) {
idx -= 8;
pmpcfg = __RV_CSR_READ(CSR_PMPCFG2);
} else {
idx -= 12;
pmpcfg = __RV_CSR_READ(CSR_PMPCFG3);
}
idx = idx << 3;
return (uint8_t)((pmpcfg>>idx) & 0xFF);
#elif __RISCV_XLEN == 64
if (idx < 8) {
pmpcfg = __RV_CSR_READ(CSR_PMPCFG0);
} else {
idx -= 8;
pmpcfg = __RV_CSR_READ(CSR_PMPCFG2);
}
idx = idx << 3;
return (uint8_t)((pmpcfg>>idx) & 0xFF);
#else
// TODO Add RV128 Handling
return 0;
#endif
}
/**
* \brief Set 8bit PMPxCFG by pmp entry index
* \details Set the given pmpxcfg value to the PMPxCFG Register.
* \param [in] idx PMPx region index(0-15)
* \param [in] pmpxcfg PMPxCFG register value to set
*/
__STATIC_INLINE void __set_PMPxCFG(uint32_t idx, uint8_t pmpxcfg)
{
rv_csr_t pmpcfgx = 0;
if (idx >= __PMP_ENTRY_NUM) return;
#if __RISCV_XLEN == 32
if (idx < 4) {
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG0);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG0, pmpcfgx);
} else if ((idx >=4) && (idx < 8)) {
idx -= 4;
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG1);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG1, pmpcfgx);
} else if ((idx >=8) && (idx < 12)) {
idx -= 8;
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG2);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG2, pmpcfgx);
} else {
idx -= 12;
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG3);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG3, pmpcfgx);
}
#elif __RISCV_XLEN == 64
if (idx < 8) {
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG0);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFULL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG0, pmpcfgx);
} else {
idx -= 8;
pmpcfgx = __RV_CSR_READ(CSR_PMPCFG2);
idx = idx << 3;
pmpcfgx = (pmpcfgx & ~(0xFFULL << idx)) | ((rv_csr_t)pmpxcfg << idx);
__RV_CSR_WRITE(CSR_PMPCFG2, pmpcfgx);
}
#else
// TODO Add RV128 Handling
#endif
}
/**
* \brief Get PMPCFGx Register by index
* \details Return the content of the PMPCFGx Register.
* \param [in] idx PMPCFG CSR index(0-3)
* \return PMPCFGx Register value
* \remark
* - For RV64, only idx = 0 and idx = 2 is allowed.
* pmpcfg0 and pmpcfg2 hold the configurations
* for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
* - For RV32, pmpcfg0pmpcfg3, hold the configurations
* pmp0cfgpmp15cfg for the 16 PMP entries
*/
__STATIC_INLINE rv_csr_t __get_PMPCFGx(uint32_t idx)
{
switch (idx) {
case 0: return __RV_CSR_READ(CSR_PMPCFG0);
case 1: return __RV_CSR_READ(CSR_PMPCFG1);
case 2: return __RV_CSR_READ(CSR_PMPCFG2);
case 3: return __RV_CSR_READ(CSR_PMPCFG3);
default: return 0;
}
}
/**
* \brief Set PMPCFGx by index
* \details Write the given value to the PMPCFGx Register.
* \param [in] idx PMPCFG CSR index(0-3)
* \param [in] pmpcfg PMPCFGx Register value to set
* \remark
* - For RV64, only idx = 0 and idx = 2 is allowed.
* pmpcfg0 and pmpcfg2 hold the configurations
* for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
* - For RV32, pmpcfg0pmpcfg3, hold the configurations
* pmp0cfgpmp15cfg for the 16 PMP entries
*/
__STATIC_INLINE void __set_PMPCFGx(uint32_t idx, rv_csr_t pmpcfg)
{
switch (idx) {
case 0: __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfg); break;
case 1: __RV_CSR_WRITE(CSR_PMPCFG1, pmpcfg); break;
case 2: __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfg); break;
case 3: __RV_CSR_WRITE(CSR_PMPCFG3, pmpcfg); break;
default: return;
}
}
/**
* \brief Get PMPADDRx Register by index
* \details Return the content of the PMPADDRx Register.
* \param [in] idx PMP region index(0-15)
* \return PMPADDRx Register value
*/
__STATIC_INLINE rv_csr_t __get_PMPADDRx(uint32_t idx)
{
switch (idx) {
case 0: return __RV_CSR_READ(CSR_PMPADDR0);
case 1: return __RV_CSR_READ(CSR_PMPADDR1);
case 2: return __RV_CSR_READ(CSR_PMPADDR2);
case 3: return __RV_CSR_READ(CSR_PMPADDR3);
case 4: return __RV_CSR_READ(CSR_PMPADDR4);
case 5: return __RV_CSR_READ(CSR_PMPADDR5);
case 6: return __RV_CSR_READ(CSR_PMPADDR6);
case 7: return __RV_CSR_READ(CSR_PMPADDR7);
case 8: return __RV_CSR_READ(CSR_PMPADDR8);
case 9: return __RV_CSR_READ(CSR_PMPADDR9);
case 10: return __RV_CSR_READ(CSR_PMPADDR10);
case 11: return __RV_CSR_READ(CSR_PMPADDR11);
case 12: return __RV_CSR_READ(CSR_PMPADDR12);
case 13: return __RV_CSR_READ(CSR_PMPADDR13);
case 14: return __RV_CSR_READ(CSR_PMPADDR14);
case 15: return __RV_CSR_READ(CSR_PMPADDR15);
default: return 0;
}
}
/**
* \brief Set PMPADDRx by index
* \details Write the given value to the PMPADDRx Register.
* \param [in] idx PMP region index(0-15)
* \param [in] pmpaddr PMPADDRx Register value to set
*/
__STATIC_INLINE void __set_PMPADDRx(uint32_t idx, rv_csr_t pmpaddr)
{
switch (idx) {
case 0: __RV_CSR_WRITE(CSR_PMPADDR0, pmpaddr); break;
case 1: __RV_CSR_WRITE(CSR_PMPADDR1, pmpaddr); break;
case 2: __RV_CSR_WRITE(CSR_PMPADDR2, pmpaddr); break;
case 3: __RV_CSR_WRITE(CSR_PMPADDR3, pmpaddr); break;
case 4: __RV_CSR_WRITE(CSR_PMPADDR4, pmpaddr); break;
case 5: __RV_CSR_WRITE(CSR_PMPADDR5, pmpaddr); break;
case 6: __RV_CSR_WRITE(CSR_PMPADDR6, pmpaddr); break;
case 7: __RV_CSR_WRITE(CSR_PMPADDR7, pmpaddr); break;
case 8: __RV_CSR_WRITE(CSR_PMPADDR8, pmpaddr); break;
case 9: __RV_CSR_WRITE(CSR_PMPADDR9, pmpaddr); break;
case 10: __RV_CSR_WRITE(CSR_PMPADDR10, pmpaddr); break;
case 11: __RV_CSR_WRITE(CSR_PMPADDR11, pmpaddr); break;
case 12: __RV_CSR_WRITE(CSR_PMPADDR12, pmpaddr); break;
case 13: __RV_CSR_WRITE(CSR_PMPADDR13, pmpaddr); break;
case 14: __RV_CSR_WRITE(CSR_PMPADDR14, pmpaddr); break;
case 15: __RV_CSR_WRITE(CSR_PMPADDR15, pmpaddr); break;
default: return;
}
}
/** @} */ /* End of Doxygen Group NMSIS_Core_PMP_Functions */
#endif /* defined(__PMP_PRESENT) && (__PMP_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /** __CORE_FEATURE_PMP_H__ */

View File

@ -0,0 +1,364 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_TIMER_H__
#define __CORE_FEATURE_TIMER_H__
/*!
* @file core_feature_timer.h
* @brief System Timer feature API header file for Nuclei N/NX Core
*/
/*
* System Timer Feature Configuration Macro:
* 1. __SYSTIMER_PRESENT: Define whether Private System Timer is present or not.
* * 0: Not present
* * 1: Present
* 2. __SYSTIMER_BASEADDR: Define the base address of the System Timer.
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
/**
* \defgroup NMSIS_Core_SysTimer_Registers Register Define and Type Definitions Of System Timer
* \ingroup NMSIS_Core_Registers
* \brief Type definitions and defines for system timer registers.
*
* @{
*/
/**
* \brief Structure type to access the System Timer (SysTimer).
* \details
* Structure definition to access the system timer(SysTimer).
* \remarks
* - MSFTRST register is introduced in Nuclei N Core version 1.3(\ref __NUCLEI_N_REV >= 0x0103)
* - MSTOP register is renamed to MTIMECTL register in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
* - CMPCLREN and CLKSRC bit in MTIMECTL register is introduced in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
*/
typedef struct {
__IOM uint64_t MTIMER; /*!< Offset: 0x000 (R/W) System Timer current value 64bits Register */
__IOM uint64_t MTIMERCMP; /*!< Offset: 0x008 (R/W) System Timer compare Value 64bits Register */
__IOM uint32_t RESERVED0[0x3F8]; /*!< Offset: 0x010 - 0xFEC Reserved */
__IOM uint32_t MSFTRST; /*!< Offset: 0xFF0 (R/W) System Timer Software Core Reset Register */
__IOM uint32_t RESERVED1; /*!< Offset: 0xFF4 Reserved */
__IOM uint32_t MTIMECTL; /*!< Offset: 0xFF8 (R/W) System Timer Control Register, previously MSTOP register */
__IOM uint32_t MSIP; /*!< Offset: 0xFFC (R/W) System Timer SW interrupt Register */
} SysTimer_Type;
/* Timer Control / Status Register Definitions */
#define SysTimer_MTIMECTL_TIMESTOP_Pos 0U /*!< SysTick Timer MTIMECTL: TIMESTOP bit Position */
#define SysTimer_MTIMECTL_TIMESTOP_Msk (1UL << SysTimer_MTIMECTL_TIMESTOP_Pos) /*!< SysTick Timer MTIMECTL: TIMESTOP Mask */
#define SysTimer_MTIMECTL_CMPCLREN_Pos 1U /*!< SysTick Timer MTIMECTL: CMPCLREN bit Position */
#define SysTimer_MTIMECTL_CMPCLREN_Msk (1UL << SysTimer_MTIMECTL_CMPCLREN_Pos) /*!< SysTick Timer MTIMECTL: CMPCLREN Mask */
#define SysTimer_MTIMECTL_CLKSRC_Pos 2U /*!< SysTick Timer MTIMECTL: CLKSRC bit Position */
#define SysTimer_MTIMECTL_CLKSRC_Msk (1UL << SysTimer_MTIMECTL_CLKSRC_Pos) /*!< SysTick Timer MTIMECTL: CLKSRC Mask */
#define SysTimer_MSIP_MSIP_Pos 0U /*!< SysTick Timer MSIP: MSIP bit Position */
#define SysTimer_MSIP_MSIP_Msk (1UL << SysTimer_MSIP_MSIP_Pos) /*!< SysTick Timer MSIP: MSIP Mask */
#define SysTimer_MTIMER_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */
#define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */
#define SysTimer_MTIMECTL_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMECTL/MSTOP value Mask */
#define SysTimer_MSIP_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSIP value Mask */
#define SysTimer_MSFTRST_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSFTRST value Mask */
#define SysTimer_MSFRST_KEY (0x80000A5FUL) /*!< SysTick Timer Software Reset Request Key */
#ifndef __SYSTIMER_BASEADDR
/* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in <Device.h> */
#error "__SYSTIMER_BASEADDR is not defined, please check!"
#endif
/* System Timer Memory mapping of Device */
#define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */
#define SysTimer ((SysTimer_Type *) SysTimer_BASE) /*!< SysTick configuration struct */
/** @} */ /* end of group NMSIS_Core_SysTimer_Registers */
/* ################################## SysTimer function ############################################ */
/**
* \defgroup NMSIS_Core_SysTimer SysTimer Functions
* \brief Functions that configure the Core System Timer.
* @{
*/
/**
* \brief Set system timer load value
* \details
* This function set the system timer load value in MTIMER register.
* \param [in] value value to set system timer MTIMER register.
* \remarks
* - Load value is 64bits wide.
* - \ref SysTimer_GetLoadValue
*/
__STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)
{
SysTimer->MTIMER = value;
}
/**
* \brief Get system timer load value
* \details
* This function get the system timer current value in MTIMER register.
* \return current value(64bit) of system timer MTIMER register.
* \remarks
* - Load value is 64bits wide.
* - \ref SysTimer_SetLoadValue
*/
__STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)
{
return SysTimer->MTIMER;
}
/**
* \brief Set system timer compare value
* \details
* This function set the system Timer compare value in MTIMERCMP register.
* \param [in] value compare value to set system timer MTIMERCMP register.
* \remarks
* - Compare value is 64bits wide.
* - If compare value is larger than current value timer interrupt generate.
* - Modify the load value or compare value less to clear the interrupt.
* - \ref SysTimer_GetCompareValue
*/
__STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)
{
SysTimer->MTIMERCMP = value;
}
/**
* \brief Get system timer compare value
* \details
* This function get the system timer compare value in MTIMERCMP register.
* \return compare value of system timer MTIMERCMP register.
* \remarks
* - Compare value is 64bits wide.
* - \ref SysTimer_SetCompareValue
*/
__STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)
{
return SysTimer->MTIMERCMP;
}
/**
* \brief Enable system timer counter running
* \details
* Enable system timer counter running by clear
* TIMESTOP bit in MTIMECTL register.
*/
__STATIC_FORCEINLINE void SysTimer_Start(void)
{
SysTimer->MTIMECTL &= ~(SysTimer_MTIMECTL_TIMESTOP_Msk);
}
/**
* \brief Stop system timer counter running
* \details
* Stop system timer counter running by set
* TIMESTOP bit in MTIMECTL register.
*/
__STATIC_FORCEINLINE void SysTimer_Stop(void)
{
SysTimer->MTIMECTL |= SysTimer_MTIMECTL_TIMESTOP_Msk;
}
/**
* \brief Set system timer control value
* \details
* This function set the system timer MTIMECTL register value.
* \param [in] mctl value to set MTIMECTL register
* \remarks
* - Bit TIMESTOP is used to start and stop timer.
* Clear TIMESTOP bit to 0 to start timer, otherwise to stop timer.
* - Bit CMPCLREN is used to enable auto MTIMER clear to zero when MTIMER >= MTIMERCMP.
* Clear CMPCLREN bit to 0 to stop auto clear MTIMER feature, otherwise to enable it.
* - Bit CLKSRC is used to select timer clock source.
* Clear CLKSRC bit to 0 to use *mtime_toggle_a*, otherwise use *core_clk_aon*
* - \ref SysTimer_GetControlValue
*/
__STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
{
SysTimer->MTIMECTL = (mctl & SysTimer_MTIMECTL_Msk);
}
/**
* \brief Get system timer control value
* \details
* This function get the system timer MTIMECTL register value.
* \return MTIMECTL register value
* \remarks
* - \ref SysTimer_SetControlValue
*/
__STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
{
return (SysTimer->MTIMECTL & SysTimer_MTIMECTL_Msk);
}
/**
* \brief Trigger or set software interrupt via system timer
* \details
* This function set the system timer MSIP bit in MSIP register.
* \remarks
* - Set system timer MSIP bit and generate a SW interrupt.
* - \ref SysTimer_ClearSWIRQ
* - \ref SysTimer_GetMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
{
SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
}
/**
* \brief Clear system timer software interrupt pending request
* \details
* This function clear the system timer MSIP bit in MSIP register.
* \remarks
* - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
* - \ref SysTimer_SetSWIRQ
* - \ref SysTimer_GetMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
{
SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
}
/**
* \brief Get system timer MSIP register value
* \details
* This function get the system timer MSIP register value.
* \return Value of Timer MSIP register.
* \remarks
* - Bit0 is SW interrupt flag.
* Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
* - \ref SysTimer_SetSWIRQ
* - \ref SysTimer_ClearSWIRQ
*/
__STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
{
return (uint32_t)(SysTimer->MSIP & SysTimer_MSIP_Msk);
}
/**
* \brief Set system timer MSIP register value
* \details
* This function set the system timer MSIP register value.
* \param [in] msip value to set MSIP register
*/
__STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
{
SysTimer->MSIP = (msip & SysTimer_MSIP_Msk);
}
/**
* \brief Do software reset request
* \details
* This function will do software reset request through MTIMER
* - Software need to write \ref SysTimer_MSFRST_KEY to generate software reset request
* - The software request flag can be cleared by reset operation to clear
* \remarks
* - The software reset is sent to SoC, SoC need to generate reset signal and send back to Core
* - This function will not return, it will do while(1) to wait the Core reset happened
*/
__STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
{
SysTimer->MSFTRST = SysTimer_MSFRST_KEY;
while(1);
}
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) && defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* \brief System Tick Configuration
* \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
*
* In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
* when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
* or similar function written by user, so it can produce period timer interrupt.
* \param [in] ticks Number of ticks between two interrupts.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
* auto cleared to 0 when MTIMER >= MTIMERCMP.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Config is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - If user need this function to start a period timer interrupt, then in timer interrupt handler
* routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* \sa
* - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
*/
__STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
{
SysTimer_SetLoadValue(0);
SysTimer_SetCompareValue(ticks);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimer_IRQn, 1);
ECLIC_EnableIRQ(SysTimer_IRQn);
return (0UL);
}
/**
* \brief System Tick Reload
* \details Reload the System Timer Tick when the MTIMECMP reached TIME value
*
* \param [in] ticks Number of ticks between two interrupts.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
* so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
* the system tick, if vendor want to use this timer's auto clear feature, they can define
* \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Reload is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
* \sa
* - \ref SysTimer_SetCompareValue
* - \ref SysTimer_SetLoadValue
*/
__STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
{
uint64_t cur_ticks = SysTimer->MTIMER;
uint64_t reload_ticks = ticks + cur_ticks;
if (__USUALLY(reload_ticks > cur_ticks)) {
SysTimer->MTIMERCMP = reload_ticks;
} else {
/* When added the ticks value, then the MTIMERCMP < TIMER,
* which means the MTIMERCMP is overflowed,
* so we need to reset the counter to zero */
SysTimer->MTIMER = 0;
SysTimer->MTIMERCMP = ticks;
}
return (0UL);
}
#endif /* defined(__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) */
/** @} */ /* End of Doxygen Group NMSIS_Core_SysTimer */
#endif /* defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /** __CORE_FEATURE_TIMER_H__ */

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_COMPILER_H
#define __NMSIS_COMPILER_H
#include <stdint.h>
/*!
* @file nmsis_compiler.h
* @brief NMSIS compiler generic header file
*/
#if defined ( __GNUC__ )
/** GNU GCC Compiler */
#include "nmsis_gcc.h"
#else
#error Unknown compiler.
#endif
#endif /* __NMSIS_COMPILER_H */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2009-2019 Arm Limited. All rights reserved.
* -- Adaptable modifications made for Nuclei Processors. --
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_CORE_H__
#define __NMSIS_CORE_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "nmsis_version.h"
/**
* \ingroup NMSIS_Core_VersionControl
* @{
*/
/* The following enum __NUCLEI_N_REV/__NUCLEI_NX_REV definition in this file
* is only used for doxygen documentation generation,
* The <device>.h is the real file to define it by vendor
*/
#if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
/**
* \brief Nuclei N class core revision number
* \details
* Reversion number format: [15:8] revision number, [7:0] patch number
* \attention
* This define is exclusive with \ref __NUCLEI_NX_REV
*/
#define __NUCLEI_N_REV (0x0104)
/**
* \brief Nuclei NX class core revision number
* \details
* Reversion number format: [15:8] revision number, [7:0] patch number
* \attention
* This define is exclusive with \ref __NUCLEI_N_REV
*/
#define __NUCLEI_NX_REV (0x0100)
#endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
/** @} */ /* End of Group NMSIS_Core_VersionControl */
#include "nmsis_compiler.h" /* NMSIS compiler specific defines */
/* === Include Nuclei Core Related Headers === */
/* Include core base feature header file */
#include "core_feature_base.h"
#ifndef __NMSIS_GENERIC
/* Include core eclic feature header file */
#include "core_feature_eclic.h"
/* Include core systimer feature header file */
#include "core_feature_timer.h"
#endif
/* Include core fpu feature header file */
#include "core_feature_fpu.h"
/* Include core dsp feature header file */
#include "core_feature_dsp.h"
/* Include core pmp feature header file */
#include "core_feature_pmp.h"
/* Include core cache feature header file */
#include "core_feature_cache.h"
/* Include compatiable functions header file */
#include "core_compatiable.h"
#ifdef __cplusplus
}
#endif
#endif /* __NMSIS_CORE_H__ */

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_GCC_H__
#define __NMSIS_GCC_H__
/*!
* @file nmsis_gcc.h
* @brief NMSIS compiler GCC header file
*/
#include <stdint.h>
#include "riscv_encoding.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ######################### Startup and Lowlevel Init ######################## */
/**
* \defgroup NMSIS_Core_CompilerControl Compiler Control
* \ingroup NMSIS_Core
* \brief Compiler agnostic \#define symbols for generic c/c++ source code
* \details
*
* The NMSIS-Core provides the header file <b>nmsis_compiler.h</b> with consistent \#define symbols for generate C or C++ source files that should be compiler agnostic.
* Each NMSIS compliant compiler should support the functionality described in this section.
*
* The header file <b>nmsis_compiler.h</b> is also included by each Device Header File <device.h> so that these definitions are available.
* @{
*/
/* ignore some GCC warnings */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
/* Fallback for __has_builtin */
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
/* NMSIS compiler specific defines */
/** \brief Pass information from the compiler to the assembler. */
#ifndef __ASM
#define __ASM __asm
#endif
/** \brief Recommend that function should be inlined by the compiler. */
#ifndef __INLINE
#define __INLINE inline
#endif
/** \brief Define a static function that may be inlined by the compiler. */
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
/** \brief Define a static function that should be always inlined by the compiler. */
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
/** \brief Inform the compiler that a function does not return. */
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__))
#endif
/** \brief Inform that a variable shall be retained in executable image. */
#ifndef __USED
#define __USED __attribute__((used))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
/** \brief specified the vector size of the variable, measured in bytes */
#ifndef __VECTOR_SIZE
#define __VECTOR_SIZE(x) __attribute__((vector_size(x)))
#endif
/** \brief Request smallest possible alignment. */
#ifndef __PACKED
#define __PACKED __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a structure. */
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a union. */
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint16_t write access */
__PACKED_STRUCT T_UINT16_WRITE {
uint16_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned write of a uint16_t variable. */
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint16_t read access */
__PACKED_STRUCT T_UINT16_READ {
uint16_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned read of a uint16_t variable. */
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint32_t write access */
__PACKED_STRUCT T_UINT32_WRITE {
uint32_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned write of a uint32_t variable. */
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint32_t read access */
__PACKED_STRUCT T_UINT32_READ {
uint32_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned read of a uint32_t variable. */
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
/** \brief Minimum `x` bytes alignment for a variable. */
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/** \brief Barrier to prevent compiler from reordering instructions. */
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __ASM volatile("":::"memory")
#endif
/** \brief provide the compiler with branch prediction information, the branch is usually true */
#ifndef __USUALLY
#define __USUALLY(exp) __builtin_expect((exp), 1)
#endif
/** \brief provide the compiler with branch prediction information, the branch is rarely true */
#ifndef __RARELY
#define __RARELY(exp) __builtin_expect((exp), 0)
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler. */
#ifndef __INTERRUPT
#define __INTERRUPT __attribute__((interrupt))
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_CompilerControl */
/* IO definitions (access restrictions to peripheral registers) */
/**
* \defgroup NMSIS_Core_PeriphAccess Peripheral Access
* \brief Naming conventions and optional features for accessing peripherals.
*
* The section below describes the naming conventions, requirements, and optional features
* for accessing device specific peripherals.
* Most of the rules also apply to the core peripherals.
*
* The **Device Header File <device.h>** contains typically these definition
* and also includes the core specific header files.
*
* @{
*/
/** \brief Defines 'read only' permissions */
#ifdef __cplusplus
#define __I volatile
#else
#define __I volatile const
#endif
/** \brief Defines 'write only' permissions */
#define __O volatile
/** \brief Defines 'read / write' permissions */
#define __IO volatile
/* following defines should be used for structure members */
/** \brief Defines 'read only' structure member permissions */
#define __IM volatile const
/** \brief Defines 'write only' structure member permissions */
#define __OM volatile
/** \brief Defines 'read/write' structure member permissions */
#define __IOM volatile
/**
* \brief Mask and shift a bit field value for use in a register bit range.
* \details The macro \ref _VAL2FLD uses the #define's _Pos and _Msk of the related bit
* field to shift bit-field values for assigning to a register.
*
* **Example**:
* \code
* ECLIC->CFG = _VAL2FLD(CLIC_CLICCFG_NLBIT, 3);
* \endcode
* \param[in] field Name of the register bit field.
* \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
* \return Masked and shifted value.
*/
#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
* \brief Mask and shift a register value to extract a bit filed value.
* \details The macro \ref _FLD2VAL uses the #define's _Pos and _Msk of the related bit
* field to extract the value of a bit field from a register.
*
* **Example**:
* \code
* nlbits = _FLD2VAL(CLIC_CLICCFG_NLBIT, ECLIC->CFG);
* \endcode
* \param[in] field Name of the register bit field.
* \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
* \return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/** @} */ /* end of group NMSIS_Core_PeriphAccess */
#ifdef __cplusplus
}
#endif
#endif /* __NMSIS_GCC_H__ */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_VERSION_H
#define __NMSIS_VERSION_H
/**
* \defgroup NMSIS_Core_VersionControl Version Control
* \ingroup NMSIS_Core
* \brief Version \#define symbols for NMSIS release specific C/C++ source code
* \details
*
* We followed the [semantic versioning 2.0.0](https://semver.org/) to control NMSIS version.
* The version format is **MAJOR.MINOR.PATCH**, increment the:
* 1. MAJOR version when you make incompatible API changes,
* 2. MINOR version when you add functionality in a backwards compatible manner, and
* 3. PATCH version when you make backwards compatible bug fixes.
*
* The header file `nmsis_version.h` is included by each core header so that these definitions are available.
*
* **Example Usage for NMSIS Version Check**:
* \code
* #if defined(__NMSIS_VERSION) && (__NMSIS_VERSION >= 0x00010105)
* #warning "Yes, we have NMSIS 1.1.5 or later"
* #else
* #error "We need NMSIS 1.1.5 or later!"
* #endif
* \endcode
*
* @{
*/
/*!
* \file nmsis_version.h
* \brief NMSIS Version definitions
**/
/**
* \brief Represent the NMSIS major version
* \details
* The NMSIS major version can be used to
* differentiate between NMSIS major releases.
* */
#define __NMSIS_VERSION_MAJOR (1U)
/**
* \brief Represent the NMSIS minor version
* \details
* The NMSIS minor version can be used to
* query a NMSIS release update including new features.
*
**/
#define __NMSIS_VERSION_MINOR (0U)
/**
* \brief Represent the NMSIS patch version
* \details
* The NMSIS patch version can be used to
* show bug fixes in this package.
**/
#define __NMSIS_VERSION_PATCH (1U)
/**
* \brief Represent the NMSIS Version
* \details
* NMSIS Version format: **MAJOR.MINOR.PATCH**
* * MAJOR: \ref __NMSIS_VERSION_MAJOR, stored in `bits [31:16]` of \ref __NMSIS_VERSION
* * MINOR: \ref __NMSIS_VERSION_MINOR, stored in `bits [15:8]` of \ref __NMSIS_VERSION
* * PATCH: \ref __NMSIS_VERSION_PATCH, stored in `bits [7:0]` of \ref __NMSIS_VERSION
**/
#define __NMSIS_VERSION ((__NMSIS_VERSION_MAJOR << 16U) | (__NMSIS_VERSION_MINOR << 8) | __NMSIS_VERSION_PATCH)
/** @} */ /* End of Doxygen Group NMSIS_Core_VersionControl */
#endif

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RISCV_BITS_H__
#define __RISCV_BITS_H__
#ifdef __cplusplus
extern "C" {
#endif
#if __riscv_xlen == 64
# define SLL32 sllw
# define STORE sd
# define LOAD ld
# define LWU lwu
# define LOG_REGBYTES 3
#else
# define SLL32 sll
# define STORE sw
# define LOAD lw
# define LWU lw
# define LOG_REGBYTES 2
#endif /* __riscv_xlen */
#define REGBYTES (1 << LOG_REGBYTES)
#if __riscv_flen == 64
# define FPSTORE fsd
# define FPLOAD fld
# define LOG_FPREGBYTES 3
#else
# define FPSTORE fsw
# define FPLOAD flw
# define LOG_FPREGBYTES 2
#endif /* __riscv_flen */
#define FPREGBYTES (1 << LOG_FPREGBYTES)
#define __rv_likely(x) __builtin_expect((x), 1)
#define __rv_unlikely(x) __builtin_expect((x), 0)
#define __RV_ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
#define __RV_ROUNDDOWN(a, b) ((a)/(b)*(b))
#define __RV_MAX(a, b) ((a) > (b) ? (a) : (b))
#define __RV_MIN(a, b) ((a) < (b) ? (a) : (b))
#define __RV_CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
#define __RV_EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
#define __RV_INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
#ifdef __ASSEMBLY__
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define __AC(X,Y) (X##Y)
#define _AC(X,Y) __AC(X,Y)
#define _AT(T,X) ((T)(X))
#endif /* __ASSEMBLY__ */
#define _UL(x) (_AC(x, UL))
#define _ULL(x) (_AC(x, ULL))
#define _BITUL(x) (_UL(1) << (x))
#define _BITULL(x) (_ULL(1) << (x))
#define UL(x) (_UL(x))
#define ULL(x) (_ULL(x))
// #define STR(x) XSTR(x)
// #define XSTR(x) #x
#define __STR(s) #s
#define STRINGIFY(s) __STR(s)
#ifdef __cplusplus
}
#endif
#endif /** __RISCV_BITS_H__ */

View File

@ -0,0 +1,617 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RISCV_ENCODING_H__
#define __RISCV_ENCODING_H__
#include "riscv_bits.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup NMSIS_Core_CSR_Encoding Core CSR Encodings
* \ingroup NMSIS_Core
* \brief NMSIS Core CSR Encodings
* \details
*
* The following macros are used for CSR encodings
* @{
*/
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
#define MSTATUS_HIE 0x00000004
#define MSTATUS_MIE 0x00000008
#define MSTATUS_UPIE 0x00000010
#define MSTATUS_SPIE 0x00000020
#define MSTATUS_HPIE 0x00000040
#define MSTATUS_MPIE 0x00000080
#define MSTATUS_SPP 0x00000100
#define MSTATUS_MPP 0x00001800
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
#define MSTATUS_MPRV 0x00020000
#define MSTATUS_PUM 0x00040000
#define MSTATUS_MXR 0x00080000
#define MSTATUS_VM 0x1F000000
#define MSTATUS32_SD 0x80000000
#define MSTATUS64_SD 0x8000000000000000
#define MSTATUS_FS_INITIAL 0x00002000
#define MSTATUS_FS_CLEAN 0x00004000
#define MSTATUS_FS_DIRTY 0x00006000
#define SSTATUS_UIE 0x00000001
#define SSTATUS_SIE 0x00000002
#define SSTATUS_UPIE 0x00000010
#define SSTATUS_SPIE 0x00000020
#define SSTATUS_SPP 0x00000100
#define SSTATUS_FS 0x00006000
#define SSTATUS_XS 0x00018000
#define SSTATUS_PUM 0x00040000
#define SSTATUS32_SD 0x80000000
#define SSTATUS64_SD 0x8000000000000000
#define CSR_MCACHE_CTL_IE 0x00000001
#define CSR_MCACHE_CTL_DE 0x00010000
#define DCSR_XDEBUGVER (3U<<30)
#define DCSR_NDRESET (1<<29)
#define DCSR_FULLRESET (1<<28)
#define DCSR_EBREAKM (1<<15)
#define DCSR_EBREAKH (1<<14)
#define DCSR_EBREAKS (1<<13)
#define DCSR_EBREAKU (1<<12)
#define DCSR_STOPCYCLE (1<<10)
#define DCSR_STOPTIME (1<<9)
#define DCSR_CAUSE (7<<6)
#define DCSR_DEBUGINT (1<<5)
#define DCSR_HALT (1<<3)
#define DCSR_STEP (1<<2)
#define DCSR_PRV (3<<0)
#define DCSR_CAUSE_NONE 0
#define DCSR_CAUSE_SWBP 1
#define DCSR_CAUSE_HWBP 2
#define DCSR_CAUSE_DEBUGINT 3
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
#define MCONTROL_SELECT (1<<19)
#define MCONTROL_TIMING (1<<18)
#define MCONTROL_ACTION (0x3f<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
#define MCONTROL_H (1<<5)
#define MCONTROL_S (1<<4)
#define MCONTROL_U (1<<3)
#define MCONTROL_EXECUTE (1<<2)
#define MCONTROL_STORE (1<<1)
#define MCONTROL_LOAD (1<<0)
#define MCONTROL_TYPE_NONE 0
#define MCONTROL_TYPE_MATCH 2
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
#define MCONTROL_ACTION_DEBUG_MODE 1
#define MCONTROL_ACTION_TRACE_START 2
#define MCONTROL_ACTION_TRACE_STOP 3
#define MCONTROL_ACTION_TRACE_EMIT 4
#define MCONTROL_MATCH_EQUAL 0
#define MCONTROL_MATCH_NAPOT 1
#define MCONTROL_MATCH_GE 2
#define MCONTROL_MATCH_LT 3
#define MCONTROL_MATCH_MASK_LOW 4
#define MCONTROL_MATCH_MASK_HIGH 5
#define MIP_SSIP (1 << IRQ_S_SOFT)
#define MIP_HSIP (1 << IRQ_H_SOFT)
#define MIP_MSIP (1 << IRQ_M_SOFT)
#define MIP_STIP (1 << IRQ_S_TIMER)
#define MIP_HTIP (1 << IRQ_H_TIMER)
#define MIP_MTIP (1 << IRQ_M_TIMER)
#define MIP_SEIP (1 << IRQ_S_EXT)
#define MIP_HEIP (1 << IRQ_H_EXT)
#define MIP_MEIP (1 << IRQ_M_EXT)
#define MIE_SSIE MIP_SSIP
#define MIE_HSIE MIP_HSIP
#define MIE_MSIE MIP_MSIP
#define MIE_STIE MIP_STIP
#define MIE_HTIE MIP_HTIP
#define MIE_MTIE MIP_MTIP
#define MIE_SEIE MIP_SEIP
#define MIE_HEIE MIP_HEIP
#define MIE_MEIE MIP_MEIP
/* === Nuclei custom CSR bit mask === */
#define WFE_WFE (0x1)
#define TXEVT_TXEVT (0x1)
#define SLEEPVALUE_SLEEPVALUE (0x1)
#define MCOUNTINHIBIT_IR (1<<2)
#define MCOUNTINHIBIT_CY (1<<0)
#define MILM_CTL_ILM_BPA (((1ULL<<((__riscv_xlen)-10))-1)<<10)
#define MILM_CTL_ILM_EN (1<<0)
#define MDLM_CTL_DLM_BPA (((1ULL<<((__riscv_xlen)-10))-1)<<10)
#define MDLM_CTL_DLM_EN (1<<0)
#define MSUBM_PTYP (0x3<<8)
#define MSUBM_TYP (0x3<<6)
#define MDCAUSE_MDCAUSE (0x3)
#define MMISC_CTL_NMI_CAUSE_FFF (1<<9)
#define MMISC_CTL_MISALIGN (1<<6)
#define MMISC_CTL_BPU (1<<3)
#define MCACHE_CTL_IC_EN (1<<0)
#define MCACHE_CTL_IC_SCPD_MOD (1<<1)
#define MCACHE_CTL_DC_EN (1<<16)
#define MTVT2_MTVT2EN (1<<0)
#define MTVT2_COMMON_CODE_ENTRY (((1ULL<<((__riscv_xlen)-2))-1)<<2)
#define MCFG_INFO_TEE (1<<0)
#define MCFG_INFO_ECC (1<<1)
#define MCFG_INFO_CLIC (1<<2)
#define MCFG_INFO_PLIC (1<<3)
#define MCFG_INFO_FIO (1<<4)
#define MCFG_INFO_PPI (1<<5)
#define MCFG_INFO_NICE (1<<6)
#define MCFG_INFO_ILM (1<<7)
#define MCFG_INFO_DLM (1<<8)
#define MCFG_INFO_ICACHE (1<<9)
#define MCFG_INFO_DCACHE (1<<10)
#define MICFG_IC_SET (0xF<<0)
#define MICFG_IC_WAY (0x7<<4)
#define MICFG_IC_LSIZE (0x7<<7)
#define MICFG_ILM_SIZE (0x1F<<16)
#define MICFG_ILM_XONLY (1<<21)
#define MDCFG_DC_SET (0xF<<0)
#define MDCFG_DC_WAY (0x7<<4)
#define MDCFG_DC_LSIZE (0x7<<7)
#define MDCFG_DLM_SIZE (0x1F<<16)
#define MPPICFG_INFO_PPI_SIZE (0x1F<<1)
#define MPPICFG_INFO_PPI_BPA (((1ULL<<((__riscv_xlen)-10))-1)<<10)
#define MFIOCFG_INFO_FIO_SIZE (0x1F<<1)
#define MFIOCFG_INFO_FIO_BPA (((1ULL<<((__riscv_xlen)-10))-1)<<10)
#define SIP_SSIP MIP_SSIP
#define SIP_STIP MIP_STIP
#define PRV_U 0
#define PRV_S 1
#define PRV_H 2
#define PRV_M 3
#define VM_MBARE 0
#define VM_MBB 1
#define VM_MBBID 2
#define VM_SV32 8
#define VM_SV39 9
#define VM_SV48 10
#define IRQ_S_SOFT 1
#define IRQ_H_SOFT 2
#define IRQ_M_SOFT 3
#define IRQ_S_TIMER 5
#define IRQ_H_TIMER 6
#define IRQ_M_TIMER 7
#define IRQ_S_EXT 9
#define IRQ_H_EXT 10
#define IRQ_M_EXT 11
#define IRQ_COP 12
#define IRQ_HOST 13
#define DEFAULT_RSTVEC 0x00001000
#define DEFAULT_NMIVEC 0x00001004
#define DEFAULT_MTVEC 0x00001010
#define CONFIG_STRING_ADDR 0x0000100C
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
/* === FPU FRM Rounding Mode === */
/** FPU Round to Nearest, ties to Even*/
#define FRM_RNDMODE_RNE 0x0
/** FPU Round Towards Zero */
#define FRM_RNDMODE_RTZ 0x1
/** FPU Round Down (towards -inf) */
#define FRM_RNDMODE_RDN 0x2
/** FPU Round Up (towards +inf) */
#define FRM_RNDMODE_RUP 0x3
/** FPU Round to nearest, ties to Max Magnitude */
#define FRM_RNDMODE_RMM 0x4
/**
* In instruction's rm, selects dynamic rounding mode.
* In Rounding Mode register, Invalid */
#define FRM_RNDMODE_DYN 0x7
/* === FPU FFLAGS Accrued Exceptions === */
/** FPU Inexact */
#define FFLAGS_AE_NX (1<<0)
/** FPU Underflow */
#define FFLAGS_AE_UF (1<<1)
/** FPU Overflow */
#define FFLAGS_AE_OF (1<<2)
/** FPU Divide by Zero */
#define FFLAGS_AE_DZ (1<<3)
/** FPU Invalid Operation */
#define FFLAGS_AE_NV (1<<4)
/** Floating Point Register f0-f31, eg. f0 -> FREG(0) */
#define FREG(idx) f##idx
/* === PMP CFG Bits === */
#define PMP_R 0x01
#define PMP_W 0x02
#define PMP_X 0x04
#define PMP_A 0x18
#define PMP_A_TOR 0x08
#define PMP_A_NA4 0x10
#define PMP_A_NAPOT 0x18
#define PMP_L 0x80
#define PMP_SHIFT 2
#define PMP_COUNT 16
// page table entry (PTE) fields
#define PTE_V 0x001 // Valid
#define PTE_R 0x002 // Read
#define PTE_W 0x004 // Write
#define PTE_X 0x008 // Execute
#define PTE_U 0x010 // User
#define PTE_G 0x020 // Global
#define PTE_A 0x040 // Accessed
#define PTE_D 0x080 // Dirty
#define PTE_SOFT 0x300 // Reserved for Software
#define PTE_PPN_SHIFT 10
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
#ifdef __riscv
#ifdef __riscv64
# define MSTATUS_SD MSTATUS64_SD
# define SSTATUS_SD SSTATUS64_SD
# define RISCV_PGLEVEL_BITS 9
#else
# define MSTATUS_SD MSTATUS32_SD
# define SSTATUS_SD SSTATUS32_SD
# define RISCV_PGLEVEL_BITS 10
#endif /* __riscv64 */
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
#endif /* __riscv */
#define DOWNLOAD_MODE_FLASHXIP 0
#define DOWNLOAD_MODE_FLASH 1
#define DOWNLOAD_MODE_ILM 2
#define DOWNLOAD_MODE_DDR 3
/**
* \defgroup NMSIS_Core_CSR_Registers Core CSR Registers
* \ingroup NMSIS_Core
* \brief NMSIS Core CSR Register Definitions
* \details
*
* The following macros are used for CSR Register Defintions.
* @{
*/
/* === Standard RISC-V CSR Registers === */
#define CSR_USTATUS 0x0
#define CSR_FFLAGS 0x1
#define CSR_FRM 0x2
#define CSR_FCSR 0x3
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
#define CSR_INSTRET 0xc02
#define CSR_HPMCOUNTER3 0xc03
#define CSR_HPMCOUNTER4 0xc04
#define CSR_HPMCOUNTER5 0xc05
#define CSR_HPMCOUNTER6 0xc06
#define CSR_HPMCOUNTER7 0xc07
#define CSR_HPMCOUNTER8 0xc08
#define CSR_HPMCOUNTER9 0xc09
#define CSR_HPMCOUNTER10 0xc0a
#define CSR_HPMCOUNTER11 0xc0b
#define CSR_HPMCOUNTER12 0xc0c
#define CSR_HPMCOUNTER13 0xc0d
#define CSR_HPMCOUNTER14 0xc0e
#define CSR_HPMCOUNTER15 0xc0f
#define CSR_HPMCOUNTER16 0xc10
#define CSR_HPMCOUNTER17 0xc11
#define CSR_HPMCOUNTER18 0xc12
#define CSR_HPMCOUNTER19 0xc13
#define CSR_HPMCOUNTER20 0xc14
#define CSR_HPMCOUNTER21 0xc15
#define CSR_HPMCOUNTER22 0xc16
#define CSR_HPMCOUNTER23 0xc17
#define CSR_HPMCOUNTER24 0xc18
#define CSR_HPMCOUNTER25 0xc19
#define CSR_HPMCOUNTER26 0xc1a
#define CSR_HPMCOUNTER27 0xc1b
#define CSR_HPMCOUNTER28 0xc1c
#define CSR_HPMCOUNTER29 0xc1d
#define CSR_HPMCOUNTER30 0xc1e
#define CSR_HPMCOUNTER31 0xc1f
#define CSR_SSTATUS 0x100
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
#define CSR_SBADADDR 0x143
#define CSR_SIP 0x144
#define CSR_SPTBR 0x180
#define CSR_MSTATUS 0x300
#define CSR_MISA 0x301
#define CSR_MEDELEG 0x302
#define CSR_MIDELEG 0x303
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MCOUNTEREN 0x306
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MBADADDR 0x343
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
#define CSR_PMPCFG0 0x3a0
#define CSR_PMPCFG1 0x3a1
#define CSR_PMPCFG2 0x3a2
#define CSR_PMPCFG3 0x3a3
#define CSR_PMPADDR0 0x3b0
#define CSR_PMPADDR1 0x3b1
#define CSR_PMPADDR2 0x3b2
#define CSR_PMPADDR3 0x3b3
#define CSR_PMPADDR4 0x3b4
#define CSR_PMPADDR5 0x3b5
#define CSR_PMPADDR6 0x3b6
#define CSR_PMPADDR7 0x3b7
#define CSR_PMPADDR8 0x3b8
#define CSR_PMPADDR9 0x3b9
#define CSR_PMPADDR10 0x3ba
#define CSR_PMPADDR11 0x3bb
#define CSR_PMPADDR12 0x3bc
#define CSR_PMPADDR13 0x3bd
#define CSR_PMPADDR14 0x3be
#define CSR_PMPADDR15 0x3bf
#define CSR_TSELECT 0x7a0
#define CSR_TDATA1 0x7a1
#define CSR_TDATA2 0x7a2
#define CSR_TDATA3 0x7a3
#define CSR_DCSR 0x7b0
#define CSR_DPC 0x7b1
#define CSR_DSCRATCH 0x7b2
#define CSR_MCYCLE 0xb00
#define CSR_MINSTRET 0xb02
#define CSR_MHPMCOUNTER3 0xb03
#define CSR_MHPMCOUNTER4 0xb04
#define CSR_MHPMCOUNTER5 0xb05
#define CSR_MHPMCOUNTER6 0xb06
#define CSR_MHPMCOUNTER7 0xb07
#define CSR_MHPMCOUNTER8 0xb08
#define CSR_MHPMCOUNTER9 0xb09
#define CSR_MHPMCOUNTER10 0xb0a
#define CSR_MHPMCOUNTER11 0xb0b
#define CSR_MHPMCOUNTER12 0xb0c
#define CSR_MHPMCOUNTER13 0xb0d
#define CSR_MHPMCOUNTER14 0xb0e
#define CSR_MHPMCOUNTER15 0xb0f
#define CSR_MHPMCOUNTER16 0xb10
#define CSR_MHPMCOUNTER17 0xb11
#define CSR_MHPMCOUNTER18 0xb12
#define CSR_MHPMCOUNTER19 0xb13
#define CSR_MHPMCOUNTER20 0xb14
#define CSR_MHPMCOUNTER21 0xb15
#define CSR_MHPMCOUNTER22 0xb16
#define CSR_MHPMCOUNTER23 0xb17
#define CSR_MHPMCOUNTER24 0xb18
#define CSR_MHPMCOUNTER25 0xb19
#define CSR_MHPMCOUNTER26 0xb1a
#define CSR_MHPMCOUNTER27 0xb1b
#define CSR_MHPMCOUNTER28 0xb1c
#define CSR_MHPMCOUNTER29 0xb1d
#define CSR_MHPMCOUNTER30 0xb1e
#define CSR_MHPMCOUNTER31 0xb1f
#define CSR_MUCOUNTEREN 0x320
#define CSR_MSCOUNTEREN 0x321
#define CSR_MHPMEVENT3 0x323
#define CSR_MHPMEVENT4 0x324
#define CSR_MHPMEVENT5 0x325
#define CSR_MHPMEVENT6 0x326
#define CSR_MHPMEVENT7 0x327
#define CSR_MHPMEVENT8 0x328
#define CSR_MHPMEVENT9 0x329
#define CSR_MHPMEVENT10 0x32a
#define CSR_MHPMEVENT11 0x32b
#define CSR_MHPMEVENT12 0x32c
#define CSR_MHPMEVENT13 0x32d
#define CSR_MHPMEVENT14 0x32e
#define CSR_MHPMEVENT15 0x32f
#define CSR_MHPMEVENT16 0x330
#define CSR_MHPMEVENT17 0x331
#define CSR_MHPMEVENT18 0x332
#define CSR_MHPMEVENT19 0x333
#define CSR_MHPMEVENT20 0x334
#define CSR_MHPMEVENT21 0x335
#define CSR_MHPMEVENT22 0x336
#define CSR_MHPMEVENT23 0x337
#define CSR_MHPMEVENT24 0x338
#define CSR_MHPMEVENT25 0x339
#define CSR_MHPMEVENT26 0x33a
#define CSR_MHPMEVENT27 0x33b
#define CSR_MHPMEVENT28 0x33c
#define CSR_MHPMEVENT29 0x33d
#define CSR_MHPMEVENT30 0x33e
#define CSR_MHPMEVENT31 0x33f
#define CSR_MVENDORID 0xf11
#define CSR_MARCHID 0xf12
#define CSR_MIMPID 0xf13
#define CSR_MHARTID 0xf14
#define CSR_CYCLEH 0xc80
#define CSR_TIMEH 0xc81
#define CSR_INSTRETH 0xc82
#define CSR_HPMCOUNTER3H 0xc83
#define CSR_HPMCOUNTER4H 0xc84
#define CSR_HPMCOUNTER5H 0xc85
#define CSR_HPMCOUNTER6H 0xc86
#define CSR_HPMCOUNTER7H 0xc87
#define CSR_HPMCOUNTER8H 0xc88
#define CSR_HPMCOUNTER9H 0xc89
#define CSR_HPMCOUNTER10H 0xc8a
#define CSR_HPMCOUNTER11H 0xc8b
#define CSR_HPMCOUNTER12H 0xc8c
#define CSR_HPMCOUNTER13H 0xc8d
#define CSR_HPMCOUNTER14H 0xc8e
#define CSR_HPMCOUNTER15H 0xc8f
#define CSR_HPMCOUNTER16H 0xc90
#define CSR_HPMCOUNTER17H 0xc91
#define CSR_HPMCOUNTER18H 0xc92
#define CSR_HPMCOUNTER19H 0xc93
#define CSR_HPMCOUNTER20H 0xc94
#define CSR_HPMCOUNTER21H 0xc95
#define CSR_HPMCOUNTER22H 0xc96
#define CSR_HPMCOUNTER23H 0xc97
#define CSR_HPMCOUNTER24H 0xc98
#define CSR_HPMCOUNTER25H 0xc99
#define CSR_HPMCOUNTER26H 0xc9a
#define CSR_HPMCOUNTER27H 0xc9b
#define CSR_HPMCOUNTER28H 0xc9c
#define CSR_HPMCOUNTER29H 0xc9d
#define CSR_HPMCOUNTER30H 0xc9e
#define CSR_HPMCOUNTER31H 0xc9f
#define CSR_MCYCLEH 0xb80
#define CSR_MINSTRETH 0xb82
#define CSR_MHPMCOUNTER3H 0xb83
#define CSR_MHPMCOUNTER4H 0xb84
#define CSR_MHPMCOUNTER5H 0xb85
#define CSR_MHPMCOUNTER6H 0xb86
#define CSR_MHPMCOUNTER7H 0xb87
#define CSR_MHPMCOUNTER8H 0xb88
#define CSR_MHPMCOUNTER9H 0xb89
#define CSR_MHPMCOUNTER10H 0xb8a
#define CSR_MHPMCOUNTER11H 0xb8b
#define CSR_MHPMCOUNTER12H 0xb8c
#define CSR_MHPMCOUNTER13H 0xb8d
#define CSR_MHPMCOUNTER14H 0xb8e
#define CSR_MHPMCOUNTER15H 0xb8f
#define CSR_MHPMCOUNTER16H 0xb90
#define CSR_MHPMCOUNTER17H 0xb91
#define CSR_MHPMCOUNTER18H 0xb92
#define CSR_MHPMCOUNTER19H 0xb93
#define CSR_MHPMCOUNTER20H 0xb94
#define CSR_MHPMCOUNTER21H 0xb95
#define CSR_MHPMCOUNTER22H 0xb96
#define CSR_MHPMCOUNTER23H 0xb97
#define CSR_MHPMCOUNTER24H 0xb98
#define CSR_MHPMCOUNTER25H 0xb99
#define CSR_MHPMCOUNTER26H 0xb9a
#define CSR_MHPMCOUNTER27H 0xb9b
#define CSR_MHPMCOUNTER28H 0xb9c
#define CSR_MHPMCOUNTER29H 0xb9d
#define CSR_MHPMCOUNTER30H 0xb9e
#define CSR_MHPMCOUNTER31H 0xb9f
/* === CLIC CSR Registers === */
#define CSR_MTVT 0x307
#define CSR_MNXTI 0x345
#define CSR_MINTSTATUS 0x346
#define CSR_MSCRATCHCSW 0x348
#define CSR_MSCRATCHCSWL 0x349
#define CSR_MCLICBASE 0x350
/* === Nuclei custom CSR Registers === */
#define CSR_MCOUNTINHIBIT 0x320
#define CSR_MILM_CTL 0x7C0
#define CSR_MDLM_CTL 0x7C1
#define CSR_MNVEC 0x7C3
#define CSR_MSUBM 0x7C4
#define CSR_MDCAUSE 0x7C9
#define CSR_MCACHE_CTL 0x7CA
#define CSR_MMISC_CTL 0x7D0
#define CSR_MSAVESTATUS 0x7D6
#define CSR_MSAVEEPC1 0x7D7
#define CSR_MSAVECAUSE1 0x7D8
#define CSR_MSAVEEPC2 0x7D9
#define CSR_MSAVECAUSE2 0x7DA
#define CSR_MSAVEDCAUSE1 0x7DB
#define CSR_MSAVEDCAUSE2 0x7DC
#define CSR_PUSHMSUBM 0x7EB
#define CSR_MTVT2 0x7EC
#define CSR_JALMNXTI 0x7ED
#define CSR_PUSHMCAUSE 0x7EE
#define CSR_PUSHMEPC 0x7EF
#define CSR_MPPICFG_INFO 0x7F0
#define CSR_MFIOCFG_INFO 0x7F1
#define CSR_SLEEPVALUE 0x811
#define CSR_TXEVT 0x812
#define CSR_WFE 0x810
#define CSR_MICFG_INFO 0xFC0
#define CSR_MDCFG_INFO 0xFC1
#define CSR_MCFG_INFO 0xFC2
/** @} */ /** End of Doxygen Group NMSIS_Core_CSR_Registers **/
/* Exception Code in MCAUSE CSR */
#define CAUSE_MISALIGNED_FETCH 0x0
#define CAUSE_FAULT_FETCH 0x1
#define CAUSE_ILLEGAL_INSTRUCTION 0x2
#define CAUSE_BREAKPOINT 0x3
#define CAUSE_MISALIGNED_LOAD 0x4
#define CAUSE_FAULT_LOAD 0x5
#define CAUSE_MISALIGNED_STORE 0x6
#define CAUSE_FAULT_STORE 0x7
#define CAUSE_USER_ECALL 0x8
#define CAUSE_SUPERVISOR_ECALL 0x9
#define CAUSE_HYPERVISOR_ECALL 0xa
#define CAUSE_MACHINE_ECALL 0xb
/* Exception Subcode in MDCAUSE CSR */
#define DCAUSE_FAULT_FETCH_PMP 0x1
#define DCAUSE_FAULT_FETCH_INST 0x2
#define DCAUSE_FAULT_LOAD_PMP 0x1
#define DCAUSE_FAULT_LOAD_INST 0x2
#define DCAUSE_FAULT_LOAD_NICE 0x3
#define DCAUSE_FAULT_STORE_PMP 0x1
#define DCAUSE_FAULT_STORE_INST 0x2
/** @} */ /** End of Doxygen Group NMSIS_Core_CSR_Encoding **/
#ifdef __cplusplus
}
#endif
#endif /* __RISCV_ENCODING_H__ */