大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是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主页知乎主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:浅析IAR下调试信息输出机制之半主机(Semihosting)的更多相关文章

  1. 痞子衡嵌入式:浅析IAR下调试信息输出机制之硬件UART外设

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之硬件UART外设. 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我们可以比较容易地 ...

  2. 痞子衡嵌入式:IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link / CMSIS-DAP)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 做Cortex-M内核MCU嵌入式软件开发,可用的集成开发环境( ...

  3. 痞子衡嵌入式:IAR内部C-SPY调试组件配套宏文件(.mac)用法介绍

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR内部C-SPY调试组件配套宏文件(.mac)用法. 痞子衡之前写过一篇 <JLink Script文件基础及其在IAR下调用 ...

  4. 痞子衡嵌入式:ARM Cortex-M调试那些事(1)- 4线协议标准(JTAG)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式调试里的接口标准JTAG. 在结束<ARM Cortex-M文件那些事>系列文章之后,痞子衡休整了一小段时间,但是讲课的 ...

  5. 痞子衡嵌入式:在IAR开发环境下为工程开启CRC完整性校验功能的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是在IAR开发环境下为工程开启CRC完整性校验功能的方法. CRC校验在嵌入式领域里的应用非常广,比如在通信领域,CRC检验值可以作为数据 ...

  6. 痞子衡嵌入式:大话双核i.MXRT1170之在线联合调试双核工程的三种方法(IAR篇)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170下在线联合调试双核工程的方法(基于IAR). 前段时间痞子衡写过一篇<双核i.MXRT1170之单独在线调试从 ...

  7. 痞子衡嵌入式:MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项(i.MXRT500为例)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项. 痞子衡前段时间写过一篇小文<为i.MXRT设计更 ...

  8. 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...

  9. 痞子衡嵌入式:Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link/DAPLink)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 本篇是 <IAR EWARM复位类型>.<M ...

随机推荐

  1. 如何通过A/B测试提升Push推送消息点击率?

    618电商节火热进行中,某电商App准备向用户推送一条全局活动消息,运营准备了两个推送文案: 文案A:年中囤货我们更懂你,没有大优惠怎敢惊动你:美妆个户,户外运动,医疗健康,一站式备齐,点击>& ...

  2. JVM学习笔记-从底层了解程序运行(二)

    解决JVM运行中的问题 一个案例理解常用工具 测试代码: /** * 从数据库中读取信用数据,套用模型,并把结果进行记录和传输 */ public class T15_FullGC_Problem01 ...

  3. 利用XtraDiagram.DiagramControl进行流程图形的绘制和控制

    DevExpress提供了一个比较强大的图形绘制工具,可以用于绘制各种图形,如流程图.组织机构图等等,本篇随笔介绍XtraDiagram.DiagramControl的使用,以及利用代码对其属性进行控 ...

  4. Python爬虫常用:谷歌浏览器驱动——Chromedriver 插件安装教程

    我们在做爬虫的时候经常要使用谷歌浏览器驱动,今天分享下这个Chromedriver 插件的安装方法. 第一步:打开谷歌浏览器打开设置面板 嫌枯燥的小伙伴可以点击此处找管理员小姐姐领取免费资料 第二步: ...

  5. WPF双滑块控件以及强制捕获鼠标事件焦点

    效果 概述 最近有个小需求要用双滑块表示一个取值范围,于是就简单做了个用户控件,在此记录下. 使用矩形Rectangle表示范围,椭圆Ellipse表示滑块,使用Canvas控制滑块的左右移动. 椭圆 ...

  6. java通过注解指定顺序导入excel

    自定义的属性,用来判断顺序的 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; impor ...

  7. day01--DOS常用命令

    打开CMD的方式 开始+系统+命令提示符 Win键+R输入cmd打开控制台(推荐使用) 在任意的文件夹下面,按住shift键+鼠标右键点击,在此处打开命令行窗口 资源管理器的地址栏前面加,上cmd路径 ...

  8. IO概述(概念&分类)和字节输入流+OUTputStream类&FileOutPutStream类介绍

    IO概述 什么是IO 生活中,你肯定经历过这样的场景.当你编辑一个文本文件,忘记了保存,可能文件就白白编辑了.当你的电脑上插入一个U盘,可以吧一个视频,拷贝到你的电脑硬盘里,那么数据都是在哪些设备上的 ...

  9. 【洛谷P1754 球迷购票问题】题解

    传送门 卡特兰数经典 \(\texttt{AB}\) 分拆问题. 分析: 题意相当于排列 \(n\) 个 \(\texttt A\) 和 \(n\) 个 \(\texttt B\),使得相邻 \(\t ...

  10. 清北学堂 2020 国庆J2考前综合强化 Day4

    目录 1. 题目 T1 写字符串 题目描述 Sol T2 神奇的数 题目描述 Sol T3 珠子染色 题目描述 Sol T4 病毒扩散 题目描述 Sol 算法 -- 图论 1. 题目 T1 写字符串 ...