在嵌入式開發中,調試永遠是最痛苦的環節。你是否曾經為了定位一個卡頓、死機、優先級反轉的問題而疲憊不堪?你是否希望能實時觀察系統的運行細節,比如任務切換、時間片分配、ISR 響應時間?
SystemView 解決了哪些痛點?
傳統日志靠串口輸出,信息有限、時序混亂,遇到高頻中斷或多任務調度就無能為力。而 SystemView 是 SEGGER 出品的實時跟蹤分析工具,它解決了:
任務調度不可見?→ 一目了然!
中斷響應太慢?→ 毫秒級分析!
性能瓶頸難以定位?→ 函數級耗時統計!
系統卡住沒信息?→ 最后一幀也能還原現場!
SystemView 幫你把 RTOS 從“黑盒”變成“透視玻璃”。
SystemView 的工作原理
SystemView 通過以下幾個步驟實現對嵌入式系統的實時監控:
鉤子函數植入在 RTOS 中植入鉤子函數,實時捕獲任務切換、中斷入口和退出等關鍵事件。
事件寫入 RTT 緩沖區捕獲的事件數據被寫入 MCU 內部的 RTT(Real-Time Transfer)緩沖區,這是一個高效的環形數據區。
數據通過調試接口傳輸利用 MCU 的調試接口(如 SWD),RTT 緩沖區的數據被高速傳輸到開發者的 PC 端。
PC 端實時解析與顯示SystemView PC 工具接收數據,實時解析任務執行順序、時間關系及內核對象狀態,并以圖形化界面展示。
實現低延遲與高可靠監控這種設計保證了系統狀態的實時反映,方便開發者快速定位和分析問題。
SystemView 能做什么?
SystemView 是一個可以在線調試嵌入式系統的工具,它能分析系統中哪些中斷、任務被執行了,以及它們的執行順序和時間關系。同時,它還能記錄系統中各種內核對象(如信號量、互斥量、事件、消息隊列等)的持有和釋放時間點,這對于調試復雜的多線程系統非常有效。
SystemView 能夠實現:
實時任務切換跟蹤
中斷進出時序圖
CPU 占用率統計
用戶自定義事件插樁
時間軸回放與數據保存
支持多種主流 RTOS(RT-Thread / FreeRTOS / embOS 等)
盡管 SystemView 提供了強大的系統分析能力,但其在實際部署中的門檻仍不容忽視。
傳統上,SystemView 依賴于 SEGGER 提供的 J-Link 仿真器來實現數據的實時采集和傳輸。這種方案在功能上確實成熟穩定,但對許多開發者來說,也帶來了一些不小的使用負擔:
正版 J-Link 的成本相對較高,盜版J-Link總是容易報錯;
同時,J-Link 本身并非為 SystemView 單獨設計,在多功能疊加的實際工程中,調試、下載、串口通信往往需要額外配合其他工具才能完成。
如何降低 SystemView 的使用門檻?
其實,SystemView 并不強制要求使用 J-Link——它還提供了一個 UART 模式接口,用于在不具備 SWO 或 Trace 能力的芯片上進行數據交互。這個 UART 模式的通信協議是公開的,允許通過串口發送命令、讀取 RTT 緩沖區,從而實現 SystemView 的核心功能。
那么問題來了:
既然 SystemView 可以用 UART 傳輸數據,那能不能把這些串口數據,轉發到 SWD 上的 RTT 通道,從而間接實現和 MCU 的數據交互?
剛好,我制作的多功能工具MicroLink 原本就具備RTT 通信的能力,因此可以順勢在此基礎上拓展,實現對 SystemView UART 協議的兼容與轉發。
簡單來說:
SystemView PC 工具選擇UART 模式進行通信,通過虛擬串口向 MicroLink 發送特定格式的數據;
MicroLink 內部固件識別并適配 SystemView 的 UART 協議,對數據包進行解析;
MicroLink 將接收到的指令映射為對目標 MCU 內存的讀寫操作,通過SWD 接口實現真實的數據訪問;
MCU 中運行的SystemView 嵌入式端程序將運行數據(任務調度、事件、ISR 等)寫入 RTT UpBuffer;
MicroLink從 RTT Buffer 中讀取數據,再通過串口返回給 SystemView PC 工具;
最終,SystemView 實時顯示系統運行過程,形成完整的數據回環。
從此你無需再專門購買昂貴的正版 J-Link,無需額外接線,也無需修改一行代碼。只要插上 MicroLink,打開 SystemView,選擇 UART 模式,點擊 Start,一切就緒。
MicroLink是一個在傳統 DAPLink 的基礎上進行了全面升級,集成了在線仿真器、USB 轉串口、脫機下載器、RTT 通信、SystemView 支持、拖拽燒錄以及用戶可編程自動化工具等多個功能于一體的“一站式”的調試與開發工具。
為了感謝大家的關注和支持,我準備了一波 MicroLink 抽獎活動,歡迎參與贏取這款開發好幫手!
也可以通過下方鏈接直接購買,立即提升開發效率:
https://item.taobao.com/item.htm?ft=t&id=895964393739
劃到文章末尾,獲取 MicroLink 開源資料,加入技術交流群,與更多開發者一起探索嵌入式開發的無限可能。
SystemView 移植與使用步驟
SystemView 包含兩個部分:
PC 端程序:由 SEGGER 提供的 SystemView 工具,可收集并可視化展示嵌入式系統運行時的行為,包括任務調度、中斷響應、系統事件等。支持實時顯示和數據保存以供離線分析。
嵌入式端程序:需要集成到 MCU 工程中,負責記錄運行信息并通過RTT(Real-Time Transfer)模塊實時發送到 PC。
嵌入式端程序移植步驟
只需要利用 RT-Thread 推出的 Env 工具 使能 SystemView 軟件包,并對其進行簡單的配置,就能完成 SystemView 的嵌入式端程序的配置。
以STM32 BSP stm32f103-onenet-nbiot為例,內核版本5.2.0,MicroLink固件版本V2.3.1及以上。
步驟一:在 Env 工具中進入 menuconfig 圖形化配置工具
打開 Env 工具,使用命令cd D:rt-threadbspstm32切換到 RT-Thread 源碼 BSP 根目錄下的 stm32f103-onenet-nbiot 目錄,然后輸入命令menuconfig配置工程。
利用上下鍵選中 RT-Thread online packages,按回車鍵進入下級菜單,在 tools packages 中打開 SystemView 。
步驟二:配置SystemView
Version選擇latest最新版本,其他選項不需要配置。
menuconfig 配置選項說明:
參數 | 描述 |
---|---|
App name | 應用程序的名字 |
Device name | 設備所用內核 |
Timestap freq | 時間戳頻率 (0 表示使用系統默認頻率) |
cpu freq | cpu頻率(0 表示使用系統默認頻率) |
RAM base | RAM基地址 默認值:0x2000 0000 |
Event ID offset | 事件ID的偏移 默認值:32 |
Using the Cortex-M cycle ... | 使用系統頻率作為時間戳 |
System description 0-2 | 系統描述符 "I#num=name, ..." num 是中斷標號, name 是中斷名稱 |
步驟三:打開內核鉤子函數
利用上下鍵選中 RT-Thread Kernel,按回車鍵進入下級菜單,打開 Enable hook list。
配置好選項之后,按 ESC 返回,退出并保存配置,這樣 SystemView 軟件包的使能和相關配置就完成了。
后面我們以一個具體的 demo 來講解 SystemView 工具的使用。
添加示例代碼
在文件 main.c 中添加以下代碼,然后在 main 函數中調用 demo 初始化函數demo_init();運行 demo。
/* * 程序清單:systemview 演示代碼 * * 這個例子中將創建一個動態信號量(初始值為0)及兩個動態線程,在這個兩個動態線程中 * 線程2將試圖采用永遠等待方式去持有信號量,持有成功之后發送運行標志。 * 線程1將先發送正在運行標志,然后釋放一次信號量,因線程2的優先級較高,線程2持有到信號量將線程1搶斷。 * 然后線程2發送運行標志之后,獲取不到信號量,被掛起,線程1繼續運行 */ #defineTHREAD_PRIORITY 25 #defineTHREAD_STACK_SIZE 512 #defineTHREAD_TIMESLICE 5 /* 指向信號量的指針 */ rt_sem_tsem_food; /* 線程1入口 */ voidthread1_entry(void* parameter) { while(1) { /* 線程1第一次運行 */ rt_kprintf("thread1 is run!n"); /* 釋放一次信號量 */ rt_sem_release(sem_food); /* 線程1第二次運行 */ rt_kprintf("thread1 run again!n"); /* 線程1延時1秒 */ rt_thread_delay(RT_TICK_PER_SECOND); } } /* 線程2入口 */ voidthread2_entry(void* parameter) { while(1) { /* 試圖持有信號量,并永遠等待直到持有到信號量 */ rt_sem_take(sem_food, RT_WAITING_FOREVER); /* 線程2正在運行 */ rt_kprintf("thread2 is run!n"); } } /* DEMO初始化函數 */ voiddemo_init(void) { /* 指向線程控制塊的指針 */ rt_thread_tthread1_id, thread2_id; /* 創建一個信號量,初始值是0 */ sem_food = rt_sem_create("sem_food",0, RT_IPC_FLAG_PRIO); if(sem_food == RT_NULL) { rt_kprintf("sem created fail!n"); return; } /* 創建線程1 */ thread1_id = rt_thread_create("thread1", thread1_entry, RT_NULL,/* 線程入口是thread1_entry, 參數RT_NULL */ THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if(thread1_id != RT_NULL) rt_thread_startup(thread1_id); /* 創建線程2 */ thread2_id = rt_thread_create("thread2", thread2_entry, RT_NULL,/* 線程入口是thread2_entry, 參數RT_NULL */ THREAD_STACK_SIZE, THREAD_PRIORITY -1, THREAD_TIMESLICE); if(thread2_id != RT_NULL) rt_thread_startup(thread2_id); }
PC 端SystemView 配置及使用
步驟一:下載 SystemView 分析工具
下載鏈接:
https://www.segger.com/products/development-tools/systemview/
步驟二:為 RT-Thread 添加系統描述文件
首先找到開發板目錄下的 packages 目錄,然后在 packages 目錄下找到 segger_debug-xxx 目錄,在這個目錄里面有一個 SystemView_Description 文件夾,RT-Thread 系統的描述文件就在里面,具體的目錄結構如下所示:
bsp\你自己的開發板\packages\segger_debug-xxx\SystemView_Description\SYSVIEW_RT-Thread.txt
將這個文件復制到 SystemView 工具安裝目錄下的 Description 目錄下,這樣 SystemView 就可以識別出 RT-Thread 系統了。
步驟三:連接MicroLink,啟動SystemView 功能
使用串口助手工具連接MicroLink提供的虛擬串口,并發送SystemView.start(0x20000000,1024,1)指令,來啟動MicroLink的SystemView 功能模塊。
SystemView.start(0x20000000,1024,1)
0x20000000:搜索RTT控制塊的起始地址;
1024:搜尋范圍大小;
1:啟動RTT的通道。
如上圖所示提示Find SEGGER RTT addr 0x200002ec,說明已成功啟動SystemView 功能,然后關閉串口。
如果提示no find _SEGGER_RTT addr,可以打開map文件,搜索_SEGGER_RTT 變量的地址,如下圖所示_SEGGER_RTT 地址為0X200002ec,然后將命令替換為SystemView.start(0X200002ec,1024,1)
步驟四:配置設備信息,開始錄制
雙擊打開 SystemView PC端程序,點擊Taget
選擇UART連接模式
COM口選擇剛才配置MicroLink啟動SystemView 功能的端口號,由于MicroLink的虛擬串口使用的是USB CDC模式,所以不需要配置波特率,保持默認就行。
點擊OK,啟動開始錄制按鈕,SystemView 就開始實時錄制系統信息了。
步驟五:結束錄制,分析系統
點擊結束錄制按鈕,結束錄制。將鼠標放置到時間軸窗口里,利用滾輪將事件放大到適合分析的大小
利用 SystemView 工具我們可以看出來,系統的運行確實如我們設想的那樣,線程1先開始運行,然后在釋放信號量之后被線程2搶斷。然后線程2運行,之后因獲取不到信號量被掛起,線程1繼續運行。從上面的事件列表還可以看到每個線程獲取或釋放信號量的具體時間。
在這次 demo 中,我們可以總結出系統整體:
線程切換有序、無異常延遲;
CPU 主要處于空閑狀態,說明整體系統負載非常低;
所有事件、切換、運行時間都精確呈現。
常見問題答疑(FAQ)
問題 | 解答 |
---|---|
1. 使用 SystemView 會不會影響系統性能? | 幾乎不會。SystemView 使用 SEGGER 的 RTT 技術通過 SWD 讀取內存中的 trace 數據,速度快、占用少。傳輸數據時采用memcpy拷貝到緩沖區,不會頻繁打斷 CPU,數據上傳過程不會顯著占用總線帶寬,性能影響可以忽略。 |
2. RTT 緩沖區滿了會不會丟數據? | 會。若上位機沒有及時讀取 RTT 緩沖區,舊數據可能被新數據覆蓋,造成 trace 丟失。建議增大緩沖區、確保持續連接并避免暫停采集。 |
3. SystemView 支持哪些 RTOS? | 官方支持 embOS、FreeRTOS、RT-Thread、CMSIS-RTOS 等主流內核,也支持通過接口適配層(SEGGER_SYSVIEW.c/h)接入自定義 RTOS。 |
4. SystemView 能用于裸機程序嗎? | 可以,但功能受限。裸機無任務調度,只能記錄中斷或自定義打點,無法進行任務運行時間分析、調度分析等 RTOS 專屬功能。 |
5. 可以在正式發布版本中保留 SystemView 嗎? | 不建議。雖然開銷小,但 trace 功能占用 RAM/ROM 空間,也可能帶來信息泄漏風險。推薦僅在開發調試階段啟用,可用#ifdef DEBUG控制。 |
6. SystemView 支持事后分析模式嗎? | 支持。除了實時分析外,SystemView 也支持“事后分析”模式:程序運行時將 trace 數據保存到目標板上的RAM 中,之后通過 MicroLink 讀取 trace 緩沖區內容進行回放分析,適合定位偶發問題或無法在線連接場景。 |
審核編輯 黃宇
-
RTOS
+關注
關注
24文章
851瀏覽量
121155 -
可視化
+關注
關注
1文章
1262瀏覽量
21851
發布評論請先 登錄
如何在Eclipse ThreadX RTOS中集成SystemView
請問freertos可視化調試中打印任務信息是不是只可以打印一次?
可視化MES系統軟件
可視化電子看板系統的崗位需求
TensorFlow TensorBoard可視化數據流圖
三維可視化的應用和優勢
SystemView如何在RT-Thread上對系統進行調試分析?
淺談基于RTOS系統開發調試的難題
基于VSCode的嵌入式開發的可視化代碼調試方法分享
如何在Ubuntu下實現可視化代碼跟蹤調試
如何在項目中使用RTOS分析工具SystemView?
使用樹莓派Pico開發板制作實時音頻光譜圖可視化器

評論