这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】RISC-V架构使用cycle对接perf_counter

共2条 1/1 1 跳转至

【换取手持数字示波器】RISC-V架构使用cycle对接perf_counter工具

工程师
2024-12-24 17:58:45   被打赏 37 分(兑奖)     打赏

简介:

       根据之前在ARM-CORTEXM 架构上使用perf_counter 的经验,perf_counter 最新的代码已经将依赖的定时器计数相关的接口剥离出来,在risc-v 使用cycle 对接到对应的接口就可以将perf_counter 应用到RISC-V架构的芯片上了。

依赖计时模块的接口如下:

接口1void perfc_port_clear_system_timer_counter(void

该接口主要用在perf 需要重新初始化配置的场景,本地使用的场景没有这方年的需求,对该接口时限为空函数,对应接口调用只有此函数一处调用。

image.png

接口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);

image.png

测试结果跟之前单独使用cycle 测试结果保持一致,至此简单的修改即可将perf_counter适配到RISC-V的处理器上运行。


助工
2024-12-25 07:56:27     打赏
2楼
RISC-V架构使用cycle对接perfcounter工具



共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]