二、arm程序在debug工具介入时可以跑完但是烧录到flash中会停留在BKPT 0xAB的解决方法-程序员宅基地

技术标签: arm cortex-m  CPU  嵌入式硬件  arm  

 所谓的半主机模式:semihosting机制

        Semihosting技术将应用程序中的IO请求通过一定的通道传送到主机(host),由主机上的资源响应应用程序的IO请求, 而不是像在主机上执行本地应用程序一样,由应用程序所在的计算机响应应用程序IO请求, 也就是将目标板的输入/输出请求从应用程序代码传递到远程运行调试器的主机的一种机制。 简单来说,目标开发板上通常不会有输入/输出这些外设,开发板运行的代码想要将结果打印出来, 或者获得用户的输入,可以通过请求远程主机IO设备来实现,如:显示器,键盘等。 目标开发板执行代码中加入对输入/输出设备进行访问函数,如:printf,scanf等, 这些函数并不是目标开发板的库函数,而是远程主机交叉编译器中带有的库函数,这些库函数被编译时,编译成一条软件中断指令。 当目标开发板上电运行之后,执行到请求访问输入/输出设备指令时,产生特定中断号的软件中断SWI, 与开发板相连的调试器会先截获目标板SWI请求,由于开发板程序中也可能存在用户自定义软件中断, 为了区分二者,调试器会根据SWI的软中断号来判断是不是semihosting模式IO请求, 如果是,则取出R0寄存器里代表的具体请求号,然后使用远程主机来响应目标板具体IO请求, 而不是开发板本身去处理setmihosting请求。 semihosting仅仅是一种调试手段,它的工作原理就是利用调试器捕捉目标环境运行过程中产生SWI中断, 然后向远程主机调试环境发送对应的调试信息。 也就是说目标开发板通过特定的软件中断指令,借用了远程主机的输入输出设备实现IO请求的访问。

        Semihosting半主机调试模式,只能使用在开发板和调试主机通过仿真器连接的情况下, 也就是说脱离了主机调试环境上述代码不能正常运行。 目标开发板上执行的IO实际上是交给了远程主机来处理实现,正是因为如此,这种方式只适合在调试模式下, 真正的嵌入式系统不可能依赖于主机实现IO处理的,嵌入式系统要想独立出来实现IO请求的处理, 这就需要将输入输出库函数的底层相关硬件实现重定向。

使用ITM机制实现调试,实现printf与scanf, ITM是ARM在推出semihosting之后推出的新一代调试机制。

ITM机制要求使用SWD方式接口,并需要连接SWO线。

What is semihosting?


Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger.

11.1 What is semihosting?

Examples of these facilities include keyboard input, screen output, and disk I/O. For example, you can use this mechanism to enable functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host instead of having a screen and keyboard on the target system.

This is useful because development hardware often does not have all the input and output facilities of the final system. Semihosting enables the host computer to provide these facilities.

Semihosting is implemented by a set of defined software instructions, for example SVCs, that generate exceptions from program control. The application invokes the appropriate Semihosting call and the debug agent then handles the exception. The debug agent provides the required communication with the host.

The Semihosting interface is common across all debug agents provided by ARM. Semihosted operations work when you are debugging applications on your development platform, as shown in the following figure:

In many cases, semihosting is invoked by code within library functions. The application can also invoke the ssemihosting operation directly.

Note

ARM processors use the SVC instructions, formerly known as SWI instructions, to make semihosting calls. However, if you are compiling for an ARMv6-M or ARMv7-M, for example a Cortex-M1 or Cortex-M3 processor, semihosting is implemented using the BKPT instruction.

翻译:半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。

这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。

         半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。

         半主机接口对 ARM 公司提供的所有调试代理都是通用的。 在无需移植的情况下使用 RealView ARMulator ISS、指令集系统模型 (ISSM)、实时系统模型 (RTSM)、RealView ICE 或 RealMonitor 时,会执行半主机操作。

         标准库使用半主机模式,半主机是通过一组定义好的软件指令 (如 SVC)SVC 指令 (以前称为 SWI 指令)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。调试代理(这里的调试代理是仿真器)提供与主机之间的必需通信。也就是说使用半主机模式必须使用仿真器调试。

         ARMv7 之前的 ARM 处理器使用 SVC 指令 (以前称为 SWI 指令)进行半主机调用。 但是,如果要为 ARMv6-M 或 ARMv7-M (如 Cortex-M1 或 Cortex-M3 处理器)进行编译,请使用 BKPT 指令来实现半主机。

         简单的来说,半主机模式就是通过仿真器实现开发板在电脑上的输入和输出。和半主机模式功能相同的是ITM调试机制。 有关ITM调试机制可以参考这里semihost/ITM机制浅析以及使用JLINK通过ITM调试stm32单片机

 

      上面介绍的半主机和ITM功能相当,他们都是调试机制,开发板均借助仿真器与电脑连接,实现单片机利用主机的屏幕键盘的输入输出。

这两种机制的运行均需要仿真器,否则无法运行。

        开发式一般单片机需要独立运行,开发者应去掉仿真器,把printf函数通过单片机的外设来实现,例如通过开发板的串口,lcd或者sd卡。

        使用keil在半主机模式下,若是使用printf、 fopen等库函数库函数调用,会进入半主机模式,发生软件异常,若此时有半主机调试环境的支持(RealView ISS、ISSM、RealView ICE 和 RealMonitor)进而通过调试器与主机进行交互,则可以进入半主机模式。但是本人使用的是JLINK V9调试器,此调试器应该是不支持半主机的调试。所以程序会进入一个错误的BKPT 0xAB状态。得出结论:并不是keil5完全不支持半主机调试,是需要完全具备半主机调试的所有软硬件平台条件后才可以用半主机来调试代码。

        参考上一篇文章中作者遇到的坑,其实KEIL+Jlink是不能运行半主机模式调试的。而DS5+DSTREAM应该是可以,因为后者在按下debug按钮后,程序全速运行没有在BKPT处中断,从侧面验证了后者是支援的。但是由于printf函数的fputc也重新定向到了UART输出,所以主机host端的IDE应该是看不到相应的输入输出的。但是由于不会中断在BKPT处,所以我当时无法发现此问题。这也导致debug的代码烧录到flash无法运行。

        那么如何禁用半主机模式呢?arm development tools的手册有详细的介绍:

Using the libraries in a nonsemihosting environment
Some C library functions use semihosting. If you use the libraries in a nonsemihosting environment, you must ensure that semihosting function calls are dealt with appropriately.

1.6.4 Using the libraries in a nonsemihosting environment

If you do not want to use semihosting, either:

  • Remove all calls to semihosting functions.
  • Re-implement the lower-level functions, for example, fputc(). You are not required to re-implement all semihosting functions. You must, however, re-implement the functions you are using in your application.

    You must re-implement functions that the C library uses to isolate itself from target dependencies. For example, if you use printf() you must re-implement fputc(). If you do not use the higher-level input/output functions like printf(), you do not have to re-implement the lower-level functions like fputc().

  • Implement a handler for all of the semihosting calls to be handled in your own specific way. One such example is for the handler to intercept the calls, redirecting them to your own nonsemihosted, that is, target-specific, functions.

To guarantee that no functions using semihosting are included in your application, use either:

  • IMPORT __use_no_semihosting from armasm assembly language.
  • #pragma import(__use_no_semihosting) from C.

以上介绍到,有三种方式来解决:

        1. 应用程序中不调用任何半主机库函数

        2. 重新定义半主机库函数的low-level函数,举例,使用到printf,则重新定义fputc函数。如果不重新定义,则编译器会编译出半主机模式的指令,即会有BKPT or SVC等指令。脱离仿真器调试的应用端不能正常运行。

        3. 实现一个统一的handler来处理所有的半主机函数调用,其实就是模拟仿真器,截取半主机函数中断异常调用的行为,这个方法待研究...

还有最后一个方法:

        在应用程序中采用__use_no_semihosting的#prama代码告诉编译器不要生成任何半主机模式的代码。只需要在汇编或者c程序中添加一次即可。

在作者上一篇中的坑,其实作者已经重新定义了fputc函数,但是依然出现半主机命令。后来反汇编发现,__main的库函数调用后,__main有一步是专门处理lib的初始化,不仅仅只有printf,还有_sys_exit(),_sys_open,__ttywrch等等,猜测是因为调用了printf后这些库函数默认会被引用,但是作者只重新定义了printf,所以其它的编译后就出现了半主机模式的问题。

为了一劳永逸,最好就是直接添加#pragma import(__use_no_semihosting)。

而当添加了此#pragran后,linker就会报错,:__use_no_semihosting was requested, but _sys_exit/_sys_open/_ttywrch was referenced

所以其实还是需要重新定义上述的几个库函数的,不然无法顺利编译通过。

网上解决办法如下:

/* 告知连接器不从C库链接使用半主机的函数 */
#pragma import(__use_no_semihosting)

/* 定义 _sys_exit() 以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}

/* 标准库需要的支持类型 */
struct __FILE
{
    int handle;
};

FILE __stdout;

/*重定义fputc的另外一种方式*/
int fputc(int ch, FILE *stream)
{
    uartwriteFunc
}

添加上述代码后,就不会再报错了。_sys_open和_ttywrch也不用重新定义。

另外,arm官网有一篇专门解释BKPT 0xAB的topic,可以参考

Documentation – Arm Developerhttps://developer.arm.com/documentation/ka002219/latest

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iot_aaker/article/details/122113119

智能推荐

基于javascript对astar算法的实践(目前未完成,持续更新)_astar.js 平滑算法-程序员宅基地

文章浏览阅读166次。基于javascript对geojson数据格式的地图进行astar算法的实践对于geojson数据格式的处理点处理Astar算法主体处理效果分析对于geojson数据格式的处理pp=JSON.parse(pp) //pp为地图数据console.log(pp);var lineObclo=[];var linecooclo=[]for(i=0;i<pp.features.length;i++) { if(pp.features[i].geometry.type=="Line_astar.js 平滑算法

How To: Make VirtualBox Use Your Router’s DHCP to get an IP Address in Linux_the first address assigned to ipv6 virtual router -程序员宅基地

文章浏览阅读1.6k次。How To: Make VirtualBox Use Your Router’s DHCP to get an IP Address in Linuxhttp://r3dux.org/2009/09/how-to-make-virtualbox-use-your-routers-dhcp-to-get-an-ip-address-in-linux/r3dux | Septembe_the first address assigned to ipv6 virtual router must be link-local address.

ASP.NET中后台数据和前台控件的绑定-程序员宅基地

文章浏览阅读89次。关于ASP.NET中后台数据库和前台的数据控件的绑定问题最近一直在学习个知识点,自己创建了SQLServer数据库表,想在ASP.NET中连接数据库,并把数据库中的数据显示在前台,注意,这里的数据显示不是使用asp.net自带的数据显示控件进行数据的绑定,而是使用开源的数据表格插件DataTables。这样的显示效果要比DataGridView好看的多。下面将详细的过程记录如下,供初...

javascript页面右下角弹出类似QQ或MSN的消息提示-程序员宅基地

文章浏览阅读52次。this.caption= caption; this.message= message; this.target = target; this.action = action; this.width = width?width:200; this.height = height?height:120; this.timeout= 150; this.speed = 20; this.step = 1;

Docker学习笔记 - 构建webapp_docker sinatra-程序员宅基地

文章浏览阅读3.4k次。使用Docker构建并测试Web应用程序使用sinatra作为web框架,redis作为后方的数据库。1.1 创建Sinatra 容器dongli@ubuntu:~/Docker/Sinatra$ cat DockerfileFROM ubuntuMAINTAINER Edgar Li "[email protected]"RUN apt-g_docker sinatra

cmake 关于 link_directories 的问题_link_directories不起作用-程序员宅基地

文章浏览阅读2.1w次,点赞3次,收藏2次。见到下面这种东西,不要觉得烦,仔细听我把问题描述一下:故事背景是这样,我要写一些测试用例,于是有了个 CMakeLists.txt,内容如下:project(UNIT_TEST)cmake_minimum_required(VERSION 2.7)cmake_policy(SET CMP0015 OLD)set(APP_SRC gtest_main.cpp)add_exec_link_directories不起作用

随便推点

【趣味篇】Scratch之管道马里奥_马里奥scratch游戏-程序员宅基地

文章浏览阅读456次,点赞8次,收藏8次。游戏里的马里奥必须每次踩在管道上。_马里奥scratch游戏

SSM+基于SSM的智慧社区宠物医院 毕业设计-附源码211621_智慧宠物医院系统-程序员宅基地

文章浏览阅读227次,点赞4次,收藏4次。本文以SSM为开发技术,实现了一个智慧社区宠物医院。智慧社区宠物医院的主要使用者分为用户、管理员;管理员功能包括有:首页、取消预约、诊疗项目、科室信息、预约信息、问诊单、检查单、就诊信息、药品、药品管理、明星医生、退款信息等功能。通过这些功能模块的设计,基本上实现了整个智慧社区宠物医院 的过程。具体在系统设计上,采用了SSM的结构,后台上采用Mysql数据库,是一个非常优秀的智慧社区宠物医院 。_智慧宠物医院系统

Java使用FileReader和FileWriter类完成文本文件复制_filewriter+filereader-程序员宅基地

文章浏览阅读575次。1 import java.io.FileReader; 2 import java.io.FileWriter; 3 import java.io.IOException; 4 5 public class CopyFile { 6 public static void main(String[] args) throws IOException { 7 //创建输入流对象 8 FileReader fr=new FileReader("C:\\.._filewriter+filereader

蓝桥杯java第八届第三题--承压计算_蓝桥杯 承压计算 java-程序员宅基地

文章浏览阅读1.3k次。标题:承压计算X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。每块金属原料的外形、尺寸完全一致,但重量不同。金属材料被严格地堆放成金字塔形。 7 5 8 7 8 8 9 2 7_蓝桥杯 承压计算 java

如何使用AWS CLI的S3命令下载数据集_s3://aws-publicdatasets/common-crawl/crawl-002/201-程序员宅基地

文章浏览阅读7.8k次,点赞4次,收藏15次。1. 注册AWS账号需要翻墙,保证翻墙的时候网络稳定。要绑定一张信用卡,没有的话可以去借或者去淘宝租一个,最好自己有。注册完还要短信或者电话认证。2. 添加AWS用户参考网址:如何创建AWS用户3. 安装AWS CLI参考网址:安装AWS CLI安装pip和python选择合适版本的AWS CLI MSI安装(同时安装)验证安装结果C:\> ..._s3://aws-publicdatasets/common-crawl/crawl-002/2010/01/06/10/1262847572760_1

2021-07-10-程序员宅基地

文章浏览阅读49次。有些缺点光靠自己是没法发现的,在自己的眼中我们永远是最完美的。吾日三省吾身,只能发觉一些我自认为的缺点,而真正的缺点只能通过外人指出。旁人在一般情况下,也不会直接指出我的缺点。因为这涉及到别人的处事原则。也只有在别人压抑许久在外物譬如酒精的作用下,才肯说出自己的不满。但这往往会想捅破的窗户纸,关系肯定大不如前。如今我深知我是一个极度自卑的人,没有好看的皮囊,缺乏一定的自信,所以只能通过于比较中,紧紧抓住别的不好的方面来放大通过贬低他人来彰显自己的优越感,这无疑是一个小人之举。为人处世,言行举止,个人品德都值

推荐文章

热门文章

相关标签