简介:
根据之前在ARM-CORTEXM 架构上使用perf_counter 的经验,perf_counter 最新的代码已经将依赖的定时器计数相关的接口剥离出来,在risc-v 使用cycle 对接到对应的接口就可以将perf_counter 应用到RISC-V架构的芯片上了。
依赖计时模块的接口如下:
接口1void perfc_port_clear_system_timer_counter(void)
该接口主要用在perf 需要重新初始化配置的场景,本地使用的场景没有这方年的需求,对该接口时限为空函数,对应接口调用只有此函数一处调用。
接口2:void perfc_port_stop_system_timer_counting(void)
该接口跟接口1一样只有在perf 需要重新初始化配置的场景调用,我们对该函数实现为空函数即可。
接口3:void perfc_port_clear_system_timer_ovf_pending(void)
该接口主要用于timer 超时溢出清除处理,因本地使用的cycle 为64bit 的计数器,我们暂不考虑溢出的问题,该接口实现为空函数即可。
接口4:int64_t perfc_port_get_system_timer_elapsed(void)
该接口用于获取timer 计数当前时间计数值,对接为cycle 寄存器数据的读取处理实现如下:
int64_t perfc_port_get_system_timer_elapsed(void) { int64_t counter = 0,tmp = 0; counter = read_csr(cycle); tmp = read_csr(0xc80); counter |= tmp<<32u; return (int64_t)counter; }
接口5 int64_t perfc_port_get_system_timer_top(void)
用于读取定时器的最大计数周期为多少,配合溢出标志来使用,本地不考虑溢出该函式实现未返回0处理。
int64_t perfc_port_get_system_timer_top(void) { /* the 64bit cycle counter is not overflow */ return 0; }
接口6:bool perfc_port_is_system_timer_ovf_pending(void)
该接口用于获取定时器的溢出状态,因本地认为64bit 的计数周期足够长对于程序运行一次来说,该函数固定返回false
bool perfc_port_is_system_timer_ovf_pending(void) { /* whether the system timer overflow is pending */ return false; }
接口7: uint32_t perfc_port_get_system_timer_freq(void)
该接口用于获取timer 的工作时钟频率,cycle 对应频率核CPU主频一致,对应实现如下
uint32_t perfc_port_get_system_timer_freq(void) { extern uint32_t SystemCoreClock; /* return the system timer frequency */ return SystemCoreClock; }
接口8:bool perfc_port_init_system_timer(bool bIsTimeOccupied)
该接口用于timer 定时器初始化,对接为开启cycle ,对应实现如下:
bool perfc_port_init_system_timer(bool bIsTimeOccupied) { /* enable risc-v cpu cycle counter */ asm volatile ("csrci 0x320, 0x5"); return true; }
除了上述接口外,perf_counter 还依赖了部分CMSIS的接口,GD32VF103 实现了兼容CMSIS的驱动接口,我们使用对应的接口来适配即可,工程中添加如下修改代码.
Application/main.c | 15 +- .../RISCV/drivers/n200_func.h | 103 +++++++++- .../RISCV/drivers/nmsis_compiler.h | 105 +++++++++++ .../RISCV/drivers/nmsis_core.h | 111 +++++++++++ .../RISCV/drivers/nmsis_gcc.h | 210 +++++++++++++++++++++ Makefile | 1 - perf_counter/perfc_port_riscv_cycle.h | 4 +- 7 files changed, 533 insertions(+), 16 deletions(-) diff --git a/Application/main.c b/Application/main.c index d7941ab..e8b0272 100644 --- a/Application/main.c +++ b/Application/main.c @@ -87,9 +87,6 @@ void task2(void *p) { int i = 0; - uint64_t start = 0; - uint64_t end = 0; - uint64_t tmp = 0; for(i = 0;i < 6000000;i++) { atomic_add1(-1, (unsigned int *)&p1); @@ -102,15 +99,10 @@ void task2(void *p) for(;;) { - start = 0,end = 0; - start = read_csr(cycle); - tmp = read_csr(0xc80); - start |= tmp<<32u; + start_cycle_counter(); vTaskDelay(pdMS_TO_TICKS(5000)); - end = read_csr(cycle); - tmp = read_csr(0xc80); - end |= tmp<<32u; - printf("%lu\n",(uint32_t)(end -start)); + int64_t lCycleUsed = stop_cycle_counter(); + printf("cycle counter %ld.\n",(uint32_t)lCycleUsed); } //char *taskStatus = (char *)pvPortMalloc( uxTaskGetNumberOfTasks() * sizeof( TaskStatus_t ) ); @@ -237,6 +229,7 @@ int main(void) #if UARTLOGEN uart_log_init(); #endif + init_cycle_counter(false); show_version(); /* 初始化led PA1/PA2/PC13 */ rcu_periph_clock_enable(RCU_GPIOA); diff --git a/GD32VF103_Firmware_Library/RISCV/drivers/n200_func.h b/GD32VF103_Firmware_Library/RISCV/drivers/n200_func.h index 6531d0b..07b69f7 100644 --- a/GD32VF103_Firmware_Library/RISCV/drivers/n200_func.h +++ b/GD32VF103_Firmware_Library/RISCV/drivers/n200_func.h @@ -7,6 +7,7 @@ #include <stddef.h> #include "n200_timer.h" #include "n200_eclic.h" +#include "nmsis_compiler.h" #define ECLIC_GROUP_LEVEL0_PRIO4 0 #define ECLIC_GROUP_LEVEL1_PRIO3 1 @@ -58,11 +59,11 @@ uint8_t eclic_get_cliccfg (); void eclic_set_mth (uint8_t mth); uint8_t eclic_get_mth(); -//sets nlbits +//sets nlbits void eclic_set_nlbits(uint8_t nlbits); -//get nlbits +//get nlbits uint8_t eclic_get_nlbits(); void eclic_set_irq_lvl(uint32_t source, uint8_t lvl); @@ -105,5 +106,103 @@ __attribute__( ( always_inline ) ) static inline void __WFE(void) { __asm volatile ("csrc 0x810, 0x1"); } +#define __STR(s) #s +#define STRINGIFY(s) __STR(s) + +/** \brief Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V */ +typedef unsigned long rv_csr_t; + +/** + * \brief CSR operation Macro for csrs instruction. + * \details + * Set csr register to be csr_content | val + * \param csr CSR macro definition defined in + * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS + * \param val Mask value to be used wih csrs instruction + */ +#define __RV_CSR_SET(csr, val) \ + ({ \ + rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrs " STRINGIFY(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +/** + * \brief CSR operation Macro for csrc instruction. + * \details + * Set csr register to be csr_content & ~val + * \param csr CSR macro definition defined in + * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS + * \param val Mask value to be used wih csrc instruction + */ +#define __RV_CSR_CLEAR(csr, val) \ + ({ \ + rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrc " STRINGIFY(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +/** + * \brief Enable IRQ Interrupts + * \details Enables IRQ interrupts by setting the MIE-bit in the MSTATUS Register. + * \remarks + * Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __RV_CSR_SET(CSR_MSTATUS, MSTATUS_MIE); +} + +/** + * \brief Disable IRQ Interrupts + * \details Disables IRQ interrupts by clearing the MIE-bit in the MSTATUS Register. + * \remarks + * Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_MIE); +} + + +/* ===== 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 Execute fence instruction, p -> pred, s -> succ + * \details + * the FENCE instruction ensures that all memory accesses from instructions preceding + * the fence in program order (the `predecessor set`) appear earlier in the global memory order than + * memory accesses from instructions appearing after the fence in program order (the `successor set`). + * For details, please refer to The RISC-V Instruction Set Manual + * \param p predecessor set, such as iorw, rw, r, w + * \param s successor set, such as iorw, rw, r, w + **/ +#define __FENCE(p, s) __ASM volatile ("fence " #p "," #s : : : "memory") + +/** \brief Read & Write Memory barrier */ +#define __RWMB() __FENCE(iorw,iorw) + +/** \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() #endif diff --git a/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_compiler.h b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_compiler.h new file mode 100644 index 0000000..869d753 --- /dev/null +++ b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_compiler.h @@ -0,0 +1,105 @@ +/* + * 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" +#elif defined ( __ICCRISCV__ ) + /* IAR Compiler */ + #include "nmsis_iar.h" +#else + #error Unknown compiler. +#endif + +/* 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 */ + + +#endif /* __NMSIS_COMPILER_H */ + diff --git a/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_core.h b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_core.h new file mode 100644 index 0000000..16ed438 --- /dev/null +++ b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_core.h @@ -0,0 +1,111 @@ +/* + * 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. + */ +#include <stdint.h> + +#ifdef __cplusplus + extern "C" { +#endif + +#include "nmsis_version.h" + +/** + * \ingroup NMSIS_Core_VersionControl + * @{ + */ +/* The following macro __NUCLEI_N_REV/__NUCLEI_NX_REV/ + * __NUCLEI_CPU_REV/__NUCLEI_CPU_SERIES 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 + * Deprecated, this define is exclusive with \ref __NUCLEI_NX_REV + */ +#define __NUCLEI_N_REV (0x0309) +/** + * \brief Nuclei NX class core revision number + * \details + * Reversion number format: [15:8] revision number, [7:0] patch number + * \attention + * Deprecated, this define is exclusive with \ref __NUCLEI_N_REV + */ +#define __NUCLEI_NX_REV (0x0207) +/** + * \brief Nuclei CPU core revision number + * \details + * Nuclei RISC-V CPU Revision Number vX.Y.Z, eg. v3.10.1 + * \attention + * This define is exclusive with \ref __NUCLEI_CPU_SERIES + */ +#define __NUCLEI_CPU_REV (0x030A01) +/** + * \brief Nuclei CPU core series + * \details + * Nuclei RISC-V CPU Series Number, eg, 0x200, 0x300, 0x600, 0x900 + * for 200, 300, 600, 900 series. + * \attention + * This define is used together with \ref __NUCLEI_CPU_REV + */ +#define __NUCLEI_CPU_SERIES (0x0200) +#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" + +/* Include core fpu feature header file */ +#include "core_feature_fpu.h" +/* Include core dsp feature header file */ +#include "core_feature_dsp.h" +/* Include core vector feature header file */ +#include "core_feature_vector.h" +/* Include core bitmanip feature header file */ +#include "core_feature_bitmanip.h" +/* Include core pmp feature header file */ +#include "core_feature_pmp.h" +/* Include core spmp feature header file */ + #include "core_feature_spmp.h" +/* Include core cache feature header file */ +#include "core_feature_cache.h" +/* Include core cidu feature header file */ + #include "core_feature_cidu.h" + +/* Include compatiable functions header file */ +#include "core_compatiable.h" + +#ifndef __NMSIS_GENERIC +/* Include core eclic feature header file */ +#include "core_feature_eclic.h" +/* Include core plic feature header file */ +#include "core_feature_plic.h" +/* Include core systimer feature header file */ +#include "core_feature_timer.h" +#endif + +#ifdef __cplusplus +} +#endif diff --git a/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_gcc.h b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_gcc.h new file mode 100644 index 0000000..b53775d --- /dev/null +++ b/GD32VF103_Firmware_Library/RISCV/drivers/nmsis_gcc.h @@ -0,0 +1,210 @@ +/* + * 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> + +#ifdef __cplusplus + extern "C" { +#endif + +#include "riscv_encoding.h" + +/* ######################### 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. + * @{ + */ + +/* 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 run in Machine Mode. */ +#ifndef __INTERRUPT + #define __INTERRUPT __attribute__((interrupt)) +#endif + +/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Machine Mode. */ +#ifndef __MACHINE_INTERRUPT + #define __MACHINE_INTERRUPT __attribute__ ((interrupt ("machine"))) +#endif + +/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Supervisor Mode. */ +#ifndef __SUPERVISOR_INTERRUPT + #define __SUPERVISOR_INTERRUPT __attribute__ ((interrupt ("supervisor"))) +#endif + +/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in User Mode. */ +#ifndef __USER_INTERRUPT + #define __USER_INTERRUPT __attribute__ ((interrupt ("user"))) +#endif + +/** @} */ /* End of Doxygen Group NMSIS_Core_CompilerControl */ + +#ifdef __cplusplus +} +#endif +#endif /* __NMSIS_GCC_H__ */ diff --git a/Makefile b/Makefile index cc5311a..91cb873 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,6 @@ C_INCLUDES = \ -I $(TOP_DIR)/GD32VF103_Firmware_Library/GD32VF103_standard_peripheral \ -I $(TOP_DIR)/GD32VF103_Firmware_Library/GD32VF103_standard_peripheral/Include \ -I $(TOP_DIR)/GD32VF103_Firmware_Library/RISCV/drivers \ - -I $(TOP_DIR)/GD32VF103_Firmware_Library/NMSIS/Core/Include \ -I $(TOP_DIR)/freertos/include \ -I $(TOP_DIR)/freertos/portable/GCC/N200 \ -I $(TOP_DIR)/SEGGER \ diff --git a/perf_counter/perfc_port_riscv_cycle.h b/perf_counter/perfc_port_riscv_cycle.h index 99ce782..82de942 100644 --- a/perf_counter/perfc_port_riscv_cycle.h +++ b/perf_counter/perfc_port_riscv_cycle.h @@ -1,8 +1,8 @@ #ifndef PERFC_PORT_RISCV_CYCLE_H #define PERFC_PORT_RISCV_CYCLE_H -#include "core_feature_base.h" -#include "core_compatiable.h" +#include "n200_func.h" + /*============================ MACROS ========================================*/ /*============================ MACROFIED FUNCTIONS ===========================*/
添加上述代码后添加如下测试代码,使用perf_counter 来测量如下5S sleep 的CPU耗时。
start_cycle_counter(); vTaskDelay(pdMS_TO_TICKS(5000)); int64_t lCycleUsed = stop_cycle_counter(); printf("cycle counter %ld.\n",(uint32_t)lCycleUsed);
测试结果跟之前单独使用cycle 测试结果保持一致,至此简单的修改即可将perf_counter适配到RISC-V的处理器上运行。