查看: 567|回复: 0
打印 上一主题 下一主题

ARM调试技术,Semihosting与ITM

[复制链接]

45

主题

47

帖子

616

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
616
跳转到指定楼层
楼主
发表于 2018-11-19 22:35:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
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线。


It is only TX and not RX but most people just use printf for tracing anyways.

If you have a USB serial adapter, you can also use it as a SWO viewer, SWO is actually very similar to UART except using a much faster speed.

for example, with JLink, I can push it to 6MHz, which most USB serial adapters do not support.

The speed is incredibly important in timing critical debugging.

Remember, SWO is not just an application software printf style debugging, it is tied to ITM (instrumentation trace macrocell)

which enables software & hardware trace with timestamp. i.e it allows you to debug OS and application events.

It's not a problem to use SWO out in production code.

The SWO is separate from the debugger.

You can even run the SWO console w/o the debugger connected.


Target 使用 SWO 的条件

  • 硬件条件: 你得把芯片的SWO脚接到调试口上, 按JTAG接线的话这个默认已经接上了.
  • 代码条件: 你得把Printf的输出函数,替换成SWO输出函数, 其实这个函数在CMSIS库里已经提供了,就在core_cm3.h里面:

  1. /** \brief??ITM Send Character

  2. ? ? This function transmits a character via the ITM channel 0.
  3. ? ? It just returns when no debugger is connected that has booked the output.
  4. ? ? It is blocking when a debugger is connected, but the previous character send is not transmitted.

  5. ? ? \param [in]? ???ch??Character to transmit
  6. ? ? \return? ?? ?? ?? ? Character to transmit
  7. */
  8. static __INLINE uint32_t ITM_SendChar (uint32_t ch)
  9. {
  10. ??if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)??&&? ?? ?/* Trace enabled */
  11. ? ?? ?(ITM->TCR & ITM_TCR_ITMENA_Msk)? ?? ?? ?? ?? ?? ?&&? ?? ?/* ITM enabled */
  12. ? ?? ?(ITM->TER & (1UL << 0)? ?? ???)? ?? ?? ?? ?? ?? ???)? ???/* ITM Port #0 enabled */
  13. ??{
  14. ? ? while (ITM->PORT[0].u32 == 0);
  15. ? ? ITM->PORT[0].u8 = (uint8_t) ch;
  16. ??}
  17. ??return (ch);
  18. }
复制代码


Redirecting/retargeting printf() scanf()

  1. #include
  2. #include

  3. int fputc(int c, FILE *stream)
  4. {
  5. ? ?return(ITM_SendChar(c);
  6. }

  7. int fgetc(FILE *f)
  8. {
  9. ??while (ITM_CheckChar() != 1) __NOP();
  10. ??return (ITM_ReceiveChar());
  11. }
复制代码

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表