搜索
bottom↓
回复: 47

使用SWO来替代串口实现Printf打印功能

  [复制链接]

出0入0汤圆

发表于 2013-7-9 14:47:21 | 显示全部楼层 |阅读模式
本帖最后由 leavic 于 2013-7-9 14:57 编辑

不知道有多少人跟我一样不喜欢用断点仿真器什么的,长期以来我唯一的调试工具就是串口打印信息,
但串口打印有以下几个问题:
1:占用串口,这个,完全无解...
2:速度慢,真的很慢....
2:串口输出一般都是用中断方式发送,而经常调试的时候就是需要在中断中观察某些信息,中断的嵌套容易出问题,尤其是在RTOS环境下.
3:RTOS环境下还要考虑Thread Safe,这个倒是可以搞定,驱动上把互斥量用好就行了.

其实STM32之类的Cortex芯片都支持SWO输出,而我们用串口调试很多时候也只是使用TX输出而已,完全可以把Printf的串口TX Retarget到SWO这个脚上,直接使用ST-Link就可以查看打印信息了.
SWO的优势是什么呢?
1:速度快,ARM官方描述的速度:高性能数据速率 - 4 M 字节/秒 @ 50 MHz
2:不占用串口 ,其实如果你是用JTAG口的,改成SWD调试,一个脚都不会多占用.
3:因为速度快,所以基本上只需要用Block方式输出,没有中断问题
4:还是因为是Block输出,资源互斥的问题也一起被解决了

硬件条件:你得把芯片的SWO脚接到调试口上,按JTAG接线的话,这个默认已经接上了,不过很多人可能自己只用SWD的两根线,这个就没接了.

代码条件:你得把Printf的输出函数,替换成SWO输出函数,其实这个函数在CMSIS库里已经提供了,就在core_cm4.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. }
复制代码
这个会通过ITM 通道0(具体是啥我也没研究 )输出一个字符,很多人用Keil的话,Printf的都是把一个Putchar函数改成了USART的输出字符的函数吧,改成这个就行了.
我的printf以前是自己写的,代码如下:

  1. /**
  2. * @brief Use Serial Debug Wire SWO Pin to send out the
  3. *
  4. * @param pcBuff
  5. * @param length
  6. *
  7. * @return int
  8. */
  9. int SwdWrite(char * pcBuff,unsigned long length)
  10. {
  11.         int xBytesSent=0;
  12.         while (length)
  13.         {
  14.                 ITM_SendChar((uint32_t)(*pcBuff));
  15.                 length--;
  16.                 pcBuff++;
  17.                 xBytesSent++;
  18.         }
  19.         return xBytesSent++;
  20. }

  21. /**
  22. * @brief private impleted printf function,this would save a lot
  23. *            of rom&ram space compare to the built in printf
  24. *            function in the C newlib.Carefully use it inside a
  25. *            interrupt service routine.
  26. * @param fmt
  27. *
  28. * @return int
  29. */
  30. int printf(const char * fmt, ...)
  31. {


  32.         int length=0;
  33.         va_list va;

  34.         char pcBuff[200];

  35.         va_start(va, fmt);
  36.         ts_formatstring(pcBuff, fmt, va);
  37.         va_end(va);

  38.         #ifdef SERIAL_DEBUG
  39.         length = CONSOLE_UART.ulWrite(pcBuff,strlen(pcBuff));
  40.         #endif
  41.         #ifdef SWD_DEBUG
  42.         length = SwdWrite(pcBuff,strlen(pcBuff));
  43.         #endif

  44.         return (length);
  45. }
复制代码
怎么用:
PC上安装最新版的ST-Link Utility,从菜单的ST_LINK那项下面,选择Printf via SWO,就可以打开SWO查看器了

填写正确的芯片速度,后的的Port就是前面的0,如果你先用别的Port,自己查一下对应的寄存器应该怎么改吧,点Start就可以看到SWO的Printf数据了
这里可以看到SWO的速度是2Mbps(说好的4M byte呢 ),已经很快了,凑合着用吧,要什么自行车啊!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-7-9 15:17:29 | 显示全部楼层
终于有越来越多人用itm了。。。。。。。再不用,估计都要淘汰了。。。

出0入0汤圆

 楼主| 发表于 2013-7-9 15:20:32 | 显示全部楼层
jisaowang 发表于 2013-7-9 15:17
终于有越来越多人用itm了。。。。。。。再不用,估计都要淘汰了。。。 ...

ARM推广做得不够,靠工程师口口相传有困难.

出0入0汤圆

发表于 2013-7-9 15:22:44 | 显示全部楼层
leavic 发表于 2013-7-9 15:20
ARM推广做得不够,靠工程师口口相传有困难.

arm还不够??那mips之类的怎么说。。。
这事情靠的是工程师自己追踪技术发展吧,arm的推广已经非常非常好了,文档,说明,入门指南,说arm推广不好,那就真没好的了。。。

出0入0汤圆

发表于 2013-7-9 15:26:28 | 显示全部楼层
好方法,谢谢楼主共享!

出0入0汤圆

 楼主| 发表于 2013-7-9 15:26:48 | 显示全部楼层
jisaowang 发表于 2013-7-9 15:22
arm还不够??那mips之类的怎么说。。。
这事情靠的是工程师自己追踪技术发展吧,arm的推广已经非常非常 ...

很多工程师都是混混日子的,根本不会去追什么最新的技术发展,你不跟他说肉烤着吃好吃,他会继续吃生肉.
所以我认为其实很多代理商才是推动新技术普及的主要动力.

出110入0汤圆

发表于 2013-7-9 15:42:09 | 显示全部楼层
ITM里面还有个计数器,也好使……

出0入0汤圆

发表于 2013-7-9 15:52:02 | 显示全部楼层
怎样自己做一个上位机通过JLink,ULink,STLink等等来查看SWO的信息呢?这个确实值得大家好好研究研究

出0入0汤圆

发表于 2013-7-9 16:15:20 | 显示全部楼层
输入能中断方式吗?

出0入0汤圆

 楼主| 发表于 2013-7-9 16:35:28 | 显示全部楼层
Flyback 发表于 2013-7-9 15:42
ITM里面还有个计数器,也好使……

类似Timer的作用吗?用来记录一段代码的执行时间可行吗?

出0入0汤圆

 楼主| 发表于 2013-7-9 16:36:11 | 显示全部楼层
wazhiyi 发表于 2013-7-9 15:52
怎样自己做一个上位机通过JLink,ULink,STLink等等来查看SWO的信息呢?这个确实值得大家好好研究研究 ...

这个我也想过,但Windows下的编程水平实在太菜,加上又要搞USB....

出0入0汤圆

 楼主| 发表于 2013-7-9 16:38:58 | 显示全部楼层
aozima 发表于 2013-7-9 16:15
输入能中断方式吗?

还没研究过怎么输入,看了下CMSIS上的代码,好像只是个软件Buffer,没看到硬件怎么输入.

出110入0汤圆

发表于 2013-7-9 18:41:40 | 显示全部楼层
leavic 发表于 2013-7-9 16:35
类似Timer的作用吗?用来记录一段代码的执行时间可行吗?


就是个计数器 TS, 最近看ucos3才注意到的

出0入0汤圆

发表于 2013-7-9 18:53:32 | 显示全部楼层
leavic 发表于 2013-7-9 16:36
这个我也想过,但Windows下的编程水平实在太菜,加上又要搞USB....

使用 jlin karm.dll 就行吧 ?

出0入0汤圆

发表于 2013-7-9 18:56:45 | 显示全部楼层
呵呵呵。
不错。

出0入0汤圆

发表于 2013-7-11 06:41:35 来自手机 | 显示全部楼层
ewarm    iar中有这个玩意儿么?

出0入0汤圆

发表于 2013-7-11 08:40:40 | 显示全部楼层
ST LINK在目标运行时也能用吗?jlink只能在调试时使用这个功能。

出0入0汤圆

发表于 2013-7-11 08:54:42 | 显示全部楼层
make一下!!!

出0入0汤圆

 楼主| 发表于 2013-7-11 09:32:51 | 显示全部楼层
adongliu 发表于 2013-7-11 08:40
ST LINK在目标运行时也能用吗?jlink只能在调试时使用这个功能。


这两个都可以在运行时使用,因为内核一直在通过这条线往外丢数据,本质上就是另一种协议的串口外设,你只是需要正确的读取工具.
JLInk应该用Jlink自带的SWO Viewer,你如果只在Keil里看,当然是只能在调试状态看到内容.

出0入0汤圆

发表于 2013-7-11 12:54:13 | 显示全部楼层
刚才试了一下,Jlink自带的SWO Viewer无法使用,调试时则没有问题
  1. #define ITM_ENA   (*(volatile unsigned int*)0xE0000E00) // ITM Enable
  2. #define ITM_TPR   (*(volatile unsigned int*)0xE0000E40) // Trace Privilege Register
  3. #define ITM_TCR   (*(volatile unsigned int*)0xE0000E80) // ITM Trace Control Reg.
  4. #define ITM_LSR   (*(volatile unsigned int*)0xE0000FB0) // ITM Lock Status Register
  5. #define DHCSR     (*(volatile unsigned int*)0xE000EDF0) // Debug register
  6. #define DEMCR     (*(volatile unsigned int*)0xE000EDFC) // Debug register
  7. #define TPIU_ACPR (*(volatile unsigned int*)0xE0040010) // Async Clock presacler register
  8. #define TPIU_SPPR (*(volatile unsigned int*)0xE00400F0) // Selected Pin Protocol Register
  9. #define DWT_CTRL  (*(volatile unsigned int*)0xE0001000) // DWT Control Register
  10. #define FFCR      (*(volatile unsigned int*)0xE0040304) // Formatter and flush Control Register
  11. //
  12. // STIM word and byte acces
  13. #define ITM_STIM_U32  (*(volatile unsigned int*)0xE0000000)
  14. #define ITM_STIM_U8   (*(volatile char*)0xE0000000)

  15. // The stimulus port from which SWO data is received and displayed.
  16. unsigned int ITM_PORT_BIT0 = 0;

  17. // Has to be calculated according to the CPU speed and the output baud rate
  18. unsigned int TargetDiv = 1;

  19. void SWO_Enable( void )
  20. {
  21.    unsigned int StimulusRegs;
  22.    //
  23.    // Enable access to SWO registers
  24.    //
  25.    DEMCR |= ( 1 << 24 );
  26.    ITM_LSR = 0xC5ACCE55;
  27.    //
  28.    // Initially disable ITM and stimulus port
  29.    // To make sure that nothing is transferred via SWO
  30.    // when changing the SWO prescaler etc.
  31.    //
  32.    StimulusRegs = ITM_ENA;
  33.    StimulusRegs &= ~( 1 << ITM_PORT_BIT0 );
  34.    ITM_ENA = StimulusRegs; // Disable ITM stimulus port
  35.    ITM_TCR = 0;            // Disable ITM

  36.    //
  37.    // Initialize SWO (prescaler, etc.)
  38.    //
  39.    TPIU_SPPR = 0x00000002;     // Select NRZ mode
  40.    TPIU_ACPR = TargetDiv - 1;  // Example: 72/48 = 1,5 MHz
  41.    ITM_TPR = 0x00000000;
  42.    DWT_CTRL = 0x400003FE;
  43.    FFCR = 0x00000100;
  44.    //
  45.    // Enable ITM and stimulus port
  46.    //
  47.    ITM_TCR = 0x1000D; // Enable ITM
  48.    ITM_ENA = StimulusRegs | ( 1 << ITM_PORT_BIT0 ); // Enable ITM stimulus port
  49. }

  50. // Prints a character to the ITM_STIM register in order to provide data for SWO
  51. void SWO_PrintChar( char c )
  52. {
  53.    // Check if SWO is set up. If it is not,
  54.    // return to avoid that a program hangs if no debugger is connected.
  55.    //
  56.    // Check if DEBUGEN in DHCSR is set
  57.    //
  58.    if ( ( DHCSR & 1 ) != 1 )
  59.      return;

  60.    //
  61.    // Check if TRACENA in DEMCR is set
  62.    //
  63.    if ( ( DEMCR & ( 1 << 24 ) ) == 0 )
  64.      return;

  65.    //
  66.    // Check if ITM_TRC is enabled
  67.    //
  68.    if ( ( ITM_TCR & ( 1 << 22 ) ) == 1 )
  69.      return;

  70.    //
  71.    // Check if stimulus port 0 is enabled
  72.    //
  73.    if ( ( ITM_ENA & 1 ) == 0 )
  74.      return;

  75.    //
  76.    // Wait until STIMx is ready to accept at least 1 word
  77.    //
  78.    while ( ( ITM_STIM_U8 & 1 ) == 0 )
  79.    {

  80.    }

  81.    ITM_STIM_U8 = c;
  82. }

  83. // Prints a string via SWO
  84. void SWO_PrintString( const char *s )
  85. {
  86.    //
  87.    // Print out character per character
  88.    //
  89.    while ( *s )
  90.    {
  91.      SWO_PrintChar( *s++ );
  92.    }
  93. }
复制代码

出0入0汤圆

 楼主| 发表于 2013-7-11 14:20:08 | 显示全部楼层
adongliu 发表于 2013-7-11 12:54
刚才试了一下,Jlink自带的SWO Viewer无法使用,调试时则没有问题

我用CMSIS库里自带的putchar函数就可以,也没有额外的什么swo enable函数.

出0入0汤圆

发表于 2013-7-11 15:16:26 | 显示全部楼层
leavic 发表于 2013-7-11 14:20
我用CMSIS库里自带的putchar函数就可以,也没有额外的什么swo enable函数.

直接使用那个也试了,也不好使!

出0入0汤圆

 楼主| 发表于 2013-7-11 15:34:16 | 显示全部楼层
adongliu 发表于 2013-7-11 15:16
直接使用那个也试了,也不好使!

可能你其他地方的代码和这段有冲突

出0入0汤圆

发表于 2013-7-11 16:02:58 | 显示全部楼层
这个确实是个好东西

出0入0汤圆

发表于 2013-7-11 18:27:16 | 显示全部楼层
    学习了,非常好的方法啊,晚上就去试试。楼主用的是M4,M3能否支持呢?

出20入118汤圆

发表于 2013-7-11 21:41:47 | 显示全部楼层
这个必须mark

出0入0汤圆

发表于 2013-7-30 16:40:55 | 显示全部楼层
请问楼主
我用的STM32
将以下位打开之后:
DBGMCU->CR |= (1 << 5);

可以看到SWO引脚有输出串行数据,用示波器读得波特率大约为384000
即384Kb,没有上面吹的那么高。
请问,这波特率我如何设置?

出0入0汤圆

发表于 2013-7-30 17:03:02 | 显示全部楼层
好好好..................

出0入0汤圆

发表于 2013-7-31 01:24:23 | 显示全部楼层
我试过,只在MDK的Debug时,它才能输出,怎样才能让他在非Debug模式时输出信息呢?
我想通过自制的USB虚拟串口,然后自己写一个串口接收程序,从SWO帧中挑出 Print信息并显示。

出0入0汤圆

 楼主| 发表于 2013-7-31 09:10:49 | 显示全部楼层
billgates 发表于 2013-7-31 01:24
我试过,只在MDK的Debug时,它才能输出,怎样才能让他在非Debug模式时输出信息呢?
我想通过自制的USB虚拟 ...

这个问题我觉得不是Debug的问题,而是你查看的时候,SWD总线就必须被启用进入调试模式,
像ST-Link自带的工具里面,你不开MDK Debug也可以看,但ARM核肯定是被SWD总线抓到了.

出0入0汤圆

发表于 2013-7-31 09:52:26 | 显示全部楼层
好方法,谢谢楼主共享!

出0入0汤圆

发表于 2013-8-1 12:53:20 | 显示全部楼层
leavic 发表于 2013-7-31 09:10
这个问题我觉得不是Debug的问题,而是你查看的时候,SWD总线就必须被启用进入调试模式,
像ST-Link自带的工 ...

怎么整还是不行,
我想在不使用KEIL与ULINK的情况下,随时通过UART工具查看输出的printf信息,但是未能成功,
不能兄台可有兴趣一起研究一下

出0入76汤圆

发表于 2013-8-1 13:29:48 | 显示全部楼层
嗯,这个方法不错,哪天有空试试...

出50入0汤圆

发表于 2013-8-1 13:51:24 | 显示全部楼层
谢谢楼主共享。很不错的方法。

出0入0汤圆

 楼主| 发表于 2013-8-1 23:58:47 | 显示全部楼层
billgates 发表于 2013-8-1 12:53
怎么整还是不行,
我想在不使用KEIL与ULINK的情况下,随时通过UART工具查看输出的printf信息,但是未能成 ...


ST-Link Utility,我帖子上很清楚啊.或者Jlink的SWO Viewer,都不需要Keil.

出0入0汤圆

发表于 2013-8-2 10:45:46 | 显示全部楼层
leavic 发表于 2013-8-1 23:58
ST-Link Utility,我帖子上很清楚啊.或者Jlink的SWO Viewer,都不需要Keil.

请问一下,JLINK+SWOViewer,可以中途接入(单片机工作在非DEBUG模式),并查看高度信息吗?

出0入0汤圆

 楼主| 发表于 2013-8-2 13:07:23 | 显示全部楼层
billgates 发表于 2013-8-2 10:45
请问一下,JLINK+SWOViewer,可以中途接入(单片机工作在非DEBUG模式),并查看高度信息吗? ...

你为什么不去自己试一下呢?

出0入0汤圆

发表于 2013-8-2 13:23:02 | 显示全部楼层
好方法,谢谢楼主共享

出0入0汤圆

发表于 2013-8-2 13:27:02 | 显示全部楼层
为什么我的打印就很慢...

出0入0汤圆

发表于 2013-8-2 14:47:23 | 显示全部楼层
本帖最后由 billgates 于 2013-8-2 14:52 编辑
leavic 发表于 2013-8-2 13:07
你为什么不去自己试一下呢?


我只有ULINK+MDK,如果您知道,能不能直接告诉一声?
我想知道,是明否MCU的SWO输出,必须使用ULINK或JLINK通过SWD接口来开启。

我认为,SWO的printf信息,必须能使用UART随时查看才有价值。

出0入0汤圆

发表于 2013-8-2 15:01:39 | 显示全部楼层
关于ULINK2+MDK我也做了很多实验,共享一下我的信息:

1、ULINK2未找到任何脱离MDK能使用的SWO_Viewer,也就是说,目前只能在IDE的DEBUG时才能看。
2、SWO有协议封装的,其中也还包含了其它的调试信息,也就是说,对于只需要printf的人来说,它的效率不高。
3、 而且波特率不能上得太高(1Mbps都没有成功,然后试了115200),
4、 printf的效率不像楼主吹的那么厉害,是一个一个发的,与DMA相比,它会影响程序的实时性。
5、根据我目前的实验,只能通过ULINK2+MDK来开启SWO输出,也就是说,无法通过MCU的寄存器设置来开启,也意味着SWO只能是在你的办公室查看。

我之所以花时去了解了一下SWO,是因为看了楼主的这个贴子,好像我不用,还落伍了!!!
所以,还请楼主不吝赐教!

出0入0汤圆

发表于 2013-8-16 11:28:44 | 显示全部楼层
好见地呀!佩服         

出0入0汤圆

发表于 2013-8-17 08:55:30 | 显示全部楼层
期待楼上给出明确的结论,例如JLINK下如何使用。一样东西,能够推广的前提之一就是易用性

出0入0汤圆

发表于 2013-10-25 16:36:52 | 显示全部楼层
mark,谢谢分享

出0入0汤圆

发表于 2014-5-13 14:00:46 | 显示全部楼层
好东西,刚好最近也在学习使用!

出0入0汤圆

发表于 2014-5-13 21:18:36 | 显示全部楼层
好方法。可以试试去

出0入0汤圆

发表于 2014-5-30 12:58:19 | 显示全部楼层
谢谢,最近也在学习使用!

出0入0汤圆

发表于 2015-4-16 11:31:35 | 显示全部楼层
还需要自己添加一段代码,这个有点麻烦
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-19 18:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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