日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GD32VF103移植SVSTEMVIEW

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GD32VF103移植SVSTEMVIEW 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • GD32VF103移植SVSTEMVIEW
      • SystemView
        • 移植源文件加入工程
        • 修改freertos源碼
        • 添加串口移植
        • 修改systemview配置
        • 完成移植

GD32VF103移植SVSTEMVIEW

最近兆易推出了基于RISCV的MCU-GD32VF103,得到了一個GD32VF103C-START 學習板,以前只用過arm內核mcu,從沒用過RISCV內核,打算玩一下這塊板子。這次打算移植一下SEGGER 的SystemView,RTOS選擇FreeRTOS。本文開發環境為Linux Mint 19.1。

SystemView

SEGGER SystemView是一種用于嵌入式系統的實時記錄和可視化工具,可以顯示應用程序的真實運行時行為,遠遠超過調試器提供的系統洞察。在開發和使用包含多個線程和中斷的復雜嵌入式系統時,尤其有效。SystemView可以確保系統按設計執行,可以追蹤低效率,并顯示意外的交互和資源沖突,重點關注每個系統的詳細信息。并且可以免費使用。

目前官方最新版本是V3.10,在這個版本里提供了UART采集的功能,正好GD32VF103目前使用的gdlink不是jlink,在之前的systemview版本里都只支持jlink采集不支持UART采集的功能.

V3.10版本下載地址:https://www.segger.com/downloads/systemview/

但是這個頁面上并未提供串口采集移植的示例,不過在SEGGER的官方論壇里的一個帖子找到了一個示例工程:https://forum.segger.com/index.php/Thread/6874-SOLVED-SystemView-serial-port/

移植源文件加入工程

將sysvtemiew的target源碼加入工程編譯,這里需要注意用于ARM的專用匯編代碼可不必加入編譯,Syscalls的四個文件可根據需要加入編譯,這里我沒有加入.

修改freertos源碼

這個步驟分為兩步,首先根據FreeRTOSV10_Core.patch內容修改freertos源碼

然后為gd32vf103的port.c、portasm.h文件里的內核tick中斷添加trace調用包含以下四處

void vPortSysTickHandler(void) {volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME);volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP);UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();#if CONFIG_SYSTEMVIEW_ENtraceISR_ENTER();#endifuint64_t now = *mtime;now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);*mtimecmp = now;/* 調用freertos的tick增加接口 */if( xTaskIncrementTick() != pdFALSE ){#if CONFIG_SYSTEMVIEW_ENtraceISR_EXIT_TO_SCHEDULER();#endifportYIELD();}#if CONFIG_SYSTEMVIEW_ENelse{traceISR_EXIT();}#endifportCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); } #if CONFIG_SYSTEMVIEW_EN #define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } } #else #define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD() #endif

添加串口移植

創建SYSVIEW_Serial.c文件,內容如下,這里使用串口0來輸出trace采集信息。

#include "SEGGER_RTT.h" #include "SEGGER_SYSVIEW.h" #include "SYSVIEW_Serial_Conf.h" #include "gd32vf103.h"#define _SERVER_HELLO_SIZE (4) #define _TARGET_HELLO_SIZE (4)static struct {U8 NumBytesHelloRcvd;U8 NumBytesHelloSent;int ChannelID; } _SVInfo;static const U8 _abHelloMsg[_TARGET_HELLO_SIZE] = {'S', 'V', (SEGGER_SYSVIEW_VERSION / 10000), (SEGGER_SYSVIEW_VERSION / 1000) % 10}; // "Hello" message expected by SysView: [ 'S', 'V', <PROTOCOL_MAJOR>, <PROTOCOL_MINOR> ]/*** @brief This function starts and initializes a SystemView session, if necessary.* */ static void _StartSysView(void) {int r;r = SEGGER_SYSVIEW_IsStarted();if (r == 0){SEGGER_SYSVIEW_Start();} }/*** @brief This function is called when the UART receives data.* * @param Data */ static void _cbOnRx(U8 Data) {if (_SVInfo.NumBytesHelloRcvd < _SERVER_HELLO_SIZE){ // Not all bytes of <Hello> message received by SysView yet?_SVInfo.NumBytesHelloRcvd++;/* 目前版本V3.10,增加這個判斷才能正確啟動 modify by QQM */if(_SVInfo.NumBytesHelloRcvd == _SERVER_HELLO_SIZE-1){_StartSysView();}goto Done;}_StartSysView();SEGGER_RTT_WriteDownBuffer(_SVInfo.ChannelID, &Data, 1); // Write data into corresponding RTT buffer for application to read and handle accordingly Done:return; }/*** @brief This function is called when the UART should transmit data.* * @param pChar * @return int */ static int _cbOnTx(U8 *pChar) {int r;if (_SVInfo.NumBytesHelloSent < _TARGET_HELLO_SIZE){ // Not all bytes of <Hello> message sent to SysView yet?*pChar = _abHelloMsg[_SVInfo.NumBytesHelloSent];_SVInfo.NumBytesHelloSent++;r = 1;goto Done;}r = SEGGER_RTT_ReadUpBufferNoLock(_SVInfo.ChannelID, pChar, 1);if (r < 0){ // Failed to read from up buffer?r = 0;} Done:return r; }void vSYSVIEWUARTEnableTXEInterrupt(U32 NumBytes) {usart_interrupt_enable(USART0, USART_INT_TBE); }/*** @brief sysview uart handle* */ void vSYSVIEWUARTInterruptHandler(void) {U8 cChar;if(RESET != usart_interrupt_flag_get(CONFIG_SYSVIEW_UART_PORT, USART_INT_FLAG_RBNE)){/* receive data */cChar = usart_data_receive(CONFIG_SYSVIEW_UART_PORT);_cbOnRx(cChar);}if(RESET != usart_interrupt_flag_get(CONFIG_SYSVIEW_UART_PORT, USART_INT_FLAG_TBE)){if (0 == _cbOnTx(&cChar)){usart_interrupt_disable(CONFIG_SYSVIEW_UART_PORT, USART_INT_TBE);}else{/* transmit data */usart_data_transmit(CONFIG_SYSVIEW_UART_PORT, cChar);}} }/*** @brief sysview uart init* */ void vSYSVIEWUARTInit(void) {_SVInfo.ChannelID = SEGGER_SYSVIEW_GetChannelID(); // Store system view channel ID for later communicationif(CONFIG_SYSVIEW_UART_PORT == USART0){/* 初始化uart0 TX PA9 RX PA10 */rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_USART0);gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);usart_deinit(CONFIG_SYSVIEW_UART_PORT);usart_baudrate_set(CONFIG_SYSVIEW_UART_PORT, 115200U);usart_word_length_set(CONFIG_SYSVIEW_UART_PORT, USART_WL_8BIT);usart_stop_bit_set(CONFIG_SYSVIEW_UART_PORT, USART_STB_1BIT);usart_parity_config(CONFIG_SYSVIEW_UART_PORT, USART_PM_NONE);usart_hardware_flow_rts_config(CONFIG_SYSVIEW_UART_PORT, USART_RTS_DISABLE);usart_hardware_flow_cts_config(CONFIG_SYSVIEW_UART_PORT, USART_CTS_DISABLE);usart_receive_config(CONFIG_SYSVIEW_UART_PORT, USART_RECEIVE_ENABLE);usart_transmit_config(CONFIG_SYSVIEW_UART_PORT, USART_TRANSMIT_ENABLE);usart_interrupt_disable(CONFIG_SYSVIEW_UART_PORT, USART_INT_TBE);usart_interrupt_enable(CONFIG_SYSVIEW_UART_PORT, USART_INT_RBNE);usart_enable(CONFIG_SYSVIEW_UART_PORT);eclic_irq_enable(USART0_IRQn, 1, 0);} }

修改systemview配置

  • SEGGER/Config/SEGGER_RTT_Conf.h,增加SEGGER_RTT_LOCK、SEGGER_RTT_UNLOCK定義,通過eclic控制器mth閾值來關閉中斷上鎖
/********************************************************************* * * RTT lock configuration for SEGGER Embedded Studio, * Rowley CrossStudio and GCC */ #if (defined(__SES_ARM) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM)#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))#define SEGGER_RTT_LOCK() { \unsigned int LockState; \__asm volatile ("mrs %0, primask \n\t" \"movs r1, $1 \n\t" \"msr primask, r1 \n\t" \: "=r" (LockState) \: \: "r1" \);#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \: \: "r" (LockState) \: \); \}#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)#endif#define SEGGER_RTT_LOCK() { \unsigned int LockState; \__asm volatile ("mrs %0, basepri \n\t" \"mov r1, %1 \n\t" \"msr basepri, r1 \n\t" \: "=r" (LockState) \: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \: "r1" \);#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \: \: "r" (LockState) \: \); \}#elif defined(__ARM_ARCH_7A__)#define SEGGER_RTT_LOCK() { \unsigned int LockState; \__asm volatile ("mrs r1, CPSR \n\t" \"mov %0, r1 \n\t" \"orr r1, r1, #0xC0 \n\t" \"msr CPSR_c, r1 \n\t" \: "=r" (LockState) \: \: "r1" \);#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \"mrs r1, CPSR \n\t" \"bic r1, r1, #0xC0 \n\t" \"and r0, r0, #0xC0 \n\t" \"orr r1, r1, r0 \n\t" \"msr CPSR_c, r1 \n\t" \: \: "r" (LockState) \: "r0", "r1" \); \}#else#include "portmacro.h"#define SEGGER_RTT_LOCK() { \unsigned int LockState = xPortSetInterruptMask();#define SEGGER_RTT_UNLOCK() vPortClearInterruptMask(LockState); \}#endif #endif
  • SEGGER/Config/SEGGER_SYSVIEW_Conf.h,定義SEGGER_SYSVIEW_ON_EVENT_RECORDED為觸發USART_INT_TBE中斷
#ifndef SEGGER_SYSVIEW_ON_EVENT_RECORDEDextern void vSYSVIEWUARTEnableTXEInterrupt(U32 NumBytes); #define SEGGER_SYSVIEW_ON_EVENT_RECORDED(NumBytes) vSYSVIEWUARTEnableTXEInterrupt(NumBytes) // Needed for SystemView via non-J-Link Recorder. Macro to enable the UART or notify IP task. #endif
  • SEGGER/FreeRTOSV10/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c定義中斷號查詢以及tick數獲取函數,以及一些設備信息的填寫,包括設備名稱,應用名稱,內核名稱,cpu時鐘等
/********************************************************************* * * Defines, configurable * ********************************************************************** */ // The application name to be displayed in SystemViewer #define SYSVIEW_APP_NAME "GD32VF103_SYSVIEW"// The target device name #define SYSVIEW_DEVICE_NAME "GD32VF103"// The target core name #define SYSVIEW_CORE_NAME "RV32"// Frequency of the timestamp. Must match SEGGER_SYSVIEW_GET_TIMESTAMP in SEGGER_SYSVIEW_Conf.h #define SYSVIEW_TIMESTAMP_FREQ (configRTC_CLOCK_HZ)// System Frequency. SystemcoreClock is used in most CMSIS compatible projects. #define SYSVIEW_CPU_FREQ configCPU_CLOCK_HZ// The lowest RAM address used for IDs (pointers) #define SYSVIEW_RAM_BASE (0x20000000)/********************************************************************* * * _cbSendSystemDesc() * * Function description * Sends SystemView description strings. */ static void _cbSendSystemDesc(void) {SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C="SYSVIEW_CORE_NAME",O=FreeRTOS");SEGGER_SYSVIEW_SendSysDesc("I#7=SysTick"); }/********************************************************************* * * Global functions * ********************************************************************** */ void SEGGER_SYSVIEW_Conf(void) {SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ, &SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE); }U32 SEGGER_SYSVIEW_X_GetTimestamp(void) {return (*(U32 *)(TIMER_CTRL_ADDR+TIMER_MTIME)); }U32 SEGGER_SYSVIEW_X_GetInterruptId(void) {return 0xFFF&read_csr(mcause); }
  • gd32vf103_it.c 添加Application/gd32vf103_it.c到USART0_IRQHandler內
/*!\brief this function handles USART RBNE interrupt request and TBE interrupt request\param[in] none\param[out] none\retval none */ void USART0_IRQHandler(void) {#if CONFIG_SYSTEMVIEW_ENvSYSVIEWUARTInterruptHandler();#endif }

完成移植

在main函數調用SEGGER_SYSVIEW_Conf()和vSYSVIEWUARTInit()函數,創建兩個測試任務看看。

void task1(void *p) {for(;;){gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));vTaskDelay(pdMS_TO_TICKS(500));} }void task2(void *p) {char *taskStatus = (char *)pvPortMalloc( uxTaskGetNumberOfTasks() * sizeof( TaskStatus_t ) );for(;;){vTaskList(taskStatus);printf("\nTaskName\tStatus\tPRI\tStack\tTaskNumber\n%s",taskStatus);printf("current tick is %ld\n",xTaskGetTickCount());vTaskDelay(pdMS_TO_TICKS(5000));} }int main(void) { eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); //四位優先級組全配置為lvleclic_global_interrupt_enable(); //使能全局中斷#if CONFIG_SYSTEMVIEW_ENSEGGER_SYSVIEW_Conf();printf("Segger Sysview Control Block Detection Address is 0x%lx\n", (uint32_t)&_SEGGER_RTT);vSYSVIEWUARTInit();#endif#if UARTLOGENuart_log_init();#endif/* 初始化led PA7 */rcu_periph_clock_enable(RCU_GPIOA);gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);gpio_bit_reset(GPIOA, GPIO_PIN_7);xTaskCreate(task1,"task1",521,NULL,2,NULL);xTaskCreate(task2,"task2",521,NULL,2,NULL);vTaskStartScheduler(); }

編譯生成bin

通過gdb調試下載運行

打開systemview設置串口com號和波特率,這里systemview我安裝在虛擬機里,因為我的主機開發環境是linux,systemview官方一直是支持linux和mac環境的,但是V3.10這個版本存在bug,只能使用windous版本,目前官方已知道該問題后續版本會修復,但截止本文完成還未發布新版本,所以這里只能用虛擬機里跑windous版本的systemview

點擊開始采集,最終效果如下


本文使用的源碼工程已開源到我的github:https://github.com/QQxiaoming/gd32vf103_freertos

總結

以上是生活随笔為你收集整理的GD32VF103移植SVSTEMVIEW的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。