痞子衡嵌入式:淺析IAR下調試信息輸出機制之半主機(Semihosting)

来源:https://www.cnblogs.com/henjay724/archive/2022/08/23/16617826.html
-Advertisement-
Play Games

大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是IAR下調試信息輸出機制之半主機(Semihosting)。 在嵌入式世界里,輸出列印信息是一種非常常用的輔助調試手段,藉助列印信息,我們可以比較容易地定位和分析程式問題。在嵌入式應用設計里實現列印信息輸出的方式有很多,本系列將以 IA ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是IAR下調試信息輸出機制之半主機(Semihosting)

  在嵌入式世界里,輸出列印信息是一種非常常用的輔助調試手段,藉助列印信息,我們可以比較容易地定位和分析程式問題。在嵌入式應用設計里實現列印信息輸出的方式有很多,本系列將以 IAR 環境為例逐一介紹 ARM Cortex-M 內核 MCU 下列印信息輸出方法。

  上一篇文章 《IAR下調試信息輸出機制之硬體UART外設》 里我們介紹了利用 MCU 晶元內的硬體 UART 外設去做列印輸出的方式,這種方式很簡單,還可以脫離線上調試環境去使用,但畢竟占用了晶元內部的外設資源,而且調試的時候還需要額外連接串口線路,稍微麻煩了一點。今天痞子衡介紹一種在 IDE 中結合模擬器直接做列印輸出的方式,即半主機(Semihosting)技術。

  • Note: 本文使用的 IAR EWARM 軟體版本是 v9.10.2。

一、列印輸出整體框圖

  老規矩先簡介下本文介紹的列印輸出方法整體軟硬體框圖,硬體上主要是 PC 主機、MCU 目標板、一個 ARM 模擬器(DAP-Link 或者 J-Link 都可以)。

  軟體上 PC 這邊就需要 IAR 開發環境即可,這裡在編譯目標板 MCU 應用程式時,除了需要包含列印輸出相關代碼(標準 I/O 庫介面),底層介面實現必須選用 IAR 的 Semihosting 庫。當 MCU 程式運行起來後(需要保持線上調試狀態),模擬器實時捕獲代碼里的列印輸出需求,將這種 I/O 訪問需求轉移到 PC 主機上來完成,然後我們在 IAR 的 Terminal I/O 視窗里可以看到列印信息。

  上圖裡 MCU 應用程式中的 printf() 列印輸出需求到底是如何轉移到 PC 主機上 IAR 軟體里去完成的,這是本文要研究的重點。

二、Semihosting機制原理

  Semihosting 中文為半主機(半托管),這是一個在嵌入式系統中已經流傳了幾十年的技術。Semihosting 技術將應用程式中的 I/O 請求通過一定的通道傳送到主機(host),由主機上的資源響應應用程式的 I/O 請求,而不是像在主機上執行本地應用程式一樣,由應用程式所在的硬體系統來響應應用程式 I/O請求,簡單說就是將目標板的輸入/輸出請求從應用程式代碼傳遞到遠程運行調試器的主機上的一種機制。

  ARM 也定義了這種 Semihosting 機制實現,我們在目標 ARM 開發板代碼中加入 printf,scanf 等函數調用時,這些函數並不是鏈接到目標開發板的庫函數,而是遠程主機交叉編譯器中帶有的庫函數,並且這些庫函數被編譯時會額外插入軟體中斷指令,早期的 ARMv7 架構下軟中斷使用得是 SVC 指令(SWI 指令),而對於 Cortex-M 處理器(ARMv6-M 或者 ARMv7-M 架構),這個軟體中斷指令是 BKPT。

  我們可以在 ARMv6/7/8-M Architecture RM 手冊里找到 BKPT 指令定義,其中 imm8 是指定存儲在指令中的 8 位值,這個值會被處理器忽略,但是調試器可以使用它來存儲關於斷點的附加信息。

  如果 BKPT 指令是用於觸發 Semihosting 請求,其 imm8 值應該被設為 0xAB,這是 ARM 的規定。因此當模擬器捕獲到 BKPT #0xab 指令時便會讓主機響應接下來的 I/O 請求。

  現在可以觸發 Semihosting 請求了,但是 I/O 請求的種類很多,主機該如何區分呢?別擔心,ARM 還規定了 R0 寄存器來存放請求的類型(編譯器應該在 BKPT 指令前,將請求類型值放到 R0 寄存器里),我們可以在 ARM 開發者官網找到這些請求類型定義以及詳細解釋。整個 Semihosting 機制至此就清楚了,各大 IDE 只需要按照這個規定去具體實現即可。

https://developer.arm.com/documentation/dui0471/g/Semihosting/Semihosting-operations?lang=en

  關於更詳細的 Semihosting 機制,可以參考 SEGGER 整理的一篇博客 https://wiki.segger.com/Semihosting

三、IAR 對 Semihosting 機制的支持

  IAR 對 ARM 定義的 Semihosting 機制是有完善支持的,我們按上一篇的老辦法,看工程編譯鏈接後生成的 .map 文件,找到 IAR 實現 Semihosting 的相關源文件。

3.1 Terminal I/O 查看列印效果

  繼續以上一篇文章使用的 \SDK_2.11.0_EVK-MIMXRT1060\boards\evkmimxrt1060\demo_apps\hello_world\iar 工程為例,簡單改造一下工程里 hello_world.c 文件里的 main() 函數,將原來代碼全部刪掉(原來的列印輸出涉及恩智浦 SDK 封裝,本文沒必要關心其實現),只要如下一句列印即可:

#include <stdio.h>
int main(void)
{
    printf("hello world.\r\n");
    while (1);
}

  然後註意工程選項里 Library low-level interface implementation 選項,這裡我們選 Semihosted 方式,並且 stdout/stderr 選擇 Via semihosting。這時候底層 I/O 完全由 IAR 內置 Semihosting 庫來搞定了。

  我們將 MCU 目標板供上電,並連接調試器線上跑起來看看效果,在 IAR 菜單欄 View 里打開 Terminal I/O 視窗,全速運行,可以看到有 hello world. 字樣列印輸出,沒有真實的串口線路物理連接,照樣能實現列印了。

3.2 Semihosting庫I/O響應設計

  IAR 的 Terminal I/O 視窗里怎麼就能看到列印輸出的呢?我們在 \IAR Systems\Embedded Workbench 9.10.2\arm\doc\EWARM_DevelopmentGuide.ENU 手冊里找到了玄機,其實是 IAR 里的調試組件 C-SPY 負責響應調試器捕捉到的來自 MCU 的 I/O 訪問需求,並負責解釋 Semihosting 庫源碼,然後模擬了對應 I/O 操作。

3.3 Semihosting庫相關源碼實現

  現在我們再來查看生成的 hello_world.map 文件,除了 dl7M_tln.a 部分多了 XShttio.o 目標文件外,還增加了 shb_l.a 庫(裡面有一系列 .o 文件),這些增加的 .o 文件均是 Semihosting 庫相關源碼實現。我們可以在 \IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\semihosting 目錄下找到 XShttio.c 源文件,這個主要是 ARM 標準 Semihosting 實現層,但是偏 IAR 這一層的 iarttio.o、iarwrite.o、iarwstd.o 並沒有公開源碼,這可能屬於 IAR 軟體商業機密了吧。

*******************************************************************************
*** MODULE SUMMARY
***

    Module                ro code  ro data  rw data
    ------                -------  -------  -------
dl7M_tln.a: [10]
    XShttio.o                   8        8        8
    abort.o                     6
    exit.o                      4
    low_level_init.o            4
    printf.o                   40
    putchar.o                  32
    xfail_s.o                  64                 4
    xprintfsmall_nomb.o     1'281
    xprout.o                   22
    -----------------------------------------------
    Total:                  1'461        8       12

shb_l.a: [13]
    dwrite.o                   30
    exit.o                     20
    iarttio.o                 124
    iarwrite.o                 34
    iarwstd.o                  32
    write.o                    16
    -----------------------------------------------
    Total:                    256

3.4 從反彙編文件看Semihosting實現

  最後我們再從工程反彙編文件角度看一下 Semihosting 機制是不是如第二小節原理里介紹得那樣,先藉助 IAR 小工具 ielfdumparm.exe 將工程可執行文件 hello_world.out 轉換成反彙編文件 hello_world.dump。

ielfdumparm.exe --source --code .\hello_world.out -o .\hello_world.dump

  然後使用任意文本編輯器打開這個反彙編文件 hello_world.dump,在裡面搜索 BKPT 指令,確實能夠看到插入了多處軟中斷指令用於觸發 Semihosting,並且軟中斷指令前都裝載了 R0 寄存器,痞子衡截取的片段里 R0 裝載的值是 5,從 ARM 文檔里查詢,這對應了 SYS_WRITE 訪問請求。

  至此,IAR下調試信息輸出機制之半主機(Semihosting)痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時發佈到我的 博客園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。

  最後歡迎關註痞子衡個人微信公眾號【痞子衡嵌入式】,一個專註嵌入式技術的公眾號,跟著痞子衡一起玩轉嵌入式。

痞子衡嵌入式-微信二維碼 痞子衡嵌入式-微信收款二維碼 痞子衡嵌入式-支付寶收款二維碼

  衡傑(痞子衡),目前就職於恩智浦MCU系統部門,擔任嵌入式系統應用工程師。

  專欄內所有文章的轉載請註明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關註痞子衡的Github主頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關於專欄文章有任何疑問請直接在博客下麵留言,痞子衡會及時回覆免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Swagger以及knife4j基本使用 Swagger 介紹: 官網:https://swagger.io/ Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化RESTful風格的 Web 服務 Restful 面向資源 RESTful是一種架構的規範與約束、原則,符合這種規範的 ...
  • Mybatis 懶載入的使用 什麼是懶載入?懶載入的意思就是在使用的時候才去載入,不使用不去載入,相反的就叫饑餓載入或者立即載入。懶載入在Mybatis中一般是存在與聯合查詢的情況,比如查詢一個對象的同時連帶查詢相關的表對應的數據。在Mybatis中查詢可以通過ResultMap設置查詢對象返回一個 ...
  • 一、前言 我們在開發中會經常遇到一些可能會變的值,比如資料庫的密碼,一些關鍵鏈接的配置等等。 都需要我們寫在配置文件中,這樣可以把這些配置文件放到nacos上進行管理,修改nacos的配置,咱們發佈的包就可以動態的進行更新了,不需要重新修改打包在重新發包! 咱們今天就來說一說讀取配置文件中的值常見的 ...
  • Excelize 是 Go 語言編寫的 Excel 文檔基礎庫,2022年8月22日,社區正式發佈了 2.6.1 版本,該版本包含了多項新增功能、錯誤修複和相容性提升優化。 ...
  • 作者:昌維 來源:https://www.zhihu.com/question/537774494/answer/2534015588 知乎上有一個提問: 分享一個很有意思的回答。 1 我是一名 JetBrains 的忠實粉絲。我學習編程語言的經歷大概有 10 年左右,使用 JetBrains 大概 ...
  • 一、前言 在上一篇隨筆中,我向大家介紹瞭如何製作自己的 nuget 包,並沒有向大家介紹如何發佈製作好的包,今天就繼續向大家介紹如何搭建一個簡易的 nuget 私有倉庫,並上傳自己的包以供內部使用。 老規矩,今天介紹的還是在Windows系統下進行的操作,Linux系統下也可以使用 nexus 來搭 ...
  • 來瞧瞧,WPF 炫酷走馬燈! 控制項名:SpotLight 作者:WPFDevelopersOrg 原文鏈接: https://github.com/WPFDevelopersOrg/WPFDevelopers 框架使用大於等於.NET40; Visual Studio 2022; 項目使用 MIT ...
  • 一:背景 這篇我們來聊一下 PerfView 在協助 WinDbg 分析 Dump 過程中的兩個超實用技巧,可能會幫助我們快速定位最後的問題,主要有如下兩塊: 洞察記憶體泄漏中的靜態大集合變數名。 驗證當前程式的 GC 模式。 這裡就把經驗分享一下,希望讓大家少走彎路。 二:如何洞察 1. 查看靜態變 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...