首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Cortex-M4单片机上捕获和查看ITM跟踪信息?

如何在Cortex-M4单片机上捕获和查看ITM跟踪信息?
EN

Stack Overflow用户
提问于 2015-07-28 20:50:11
回答 2查看 2.4K关注 0票数 6

我想捕获、解码和查看Cortex-M4单片机(在我的例子中是Atmel SAM4S)的ITM跟踪信息。特别是,我希望捕获异常和用户跟踪数据相对于我板上的其他信号(即在同一时间线上显示所有信号和跟踪信息)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-28 20:50:11

这可以使用以下步骤来完成:

  1. 在社署模式下放置调试器。如果在Linux上使用J-Link Segger,这可以用JLinkGDBServer -if swd完成。
  2. 向MCU添加代码以启用跟踪。将比特率设置为适合您的需要的值(我使用了8 MHz)。示例Ada代码如下所示。
  3. 使用逻辑分析器从SAM4S处理器捕获TRACESWO线路上的跟踪数据。我使用了Saleae逻辑Pro 16和100 MHz采样率。
  4. 将数据转换为可由sigrok使用的格式。使用Saleae来捕获数据,这包括以下步骤:
代码语言:javascript
复制
- Capture using only the first 8 channels (so one byte per sample is exported).
- Export data as binary to `trace.bin`, writing a byte for every sample.
- Convert to a trace.sr file using:

sigrok-cli -i trace.bin -I binary:samplerate=100000000,numchannels=4 -o trace.sr

  1. trace.sr中打开PulseView文件。
  2. 将UART解码器添加到TRACESWO信道,比特率为8000000。
  3. 堆栈ARM-ITM解码器。

有关详细信息,请参阅http://www.sigrok.org/blog/new-protocol-decoders-arm-tpiu-itm-etmv3

SAM4S跟踪的示例Ada代码:

Sam4s-trace.ad:

代码语言:javascript
复制
with Interfaces;

package SAM4S.Trace is
   pragma Preelaborate;

   type Channel_Type is new Integer range 0 .. 31;
   type Value_Type is new Interfaces.Unsigned_32;

   procedure Initialize;

   procedure Put (Channel : Channel_Type;
                  Value   : Value_Type);

   procedure Put (Channel : Channel_Type;
                  Message : String);
end SAM4S.Trace;

sam4s-trace.adb:

代码语言:javascript
复制
with System;
with System.Storage_Elements; use System.Storage_Elements;

package body SAM4S.Trace is
   procedure Initialize is
      ITM_LAR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_0FB0#), Volatile;

      ITM_TCR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_0E80#), Volatile;

      ITM_TER : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_0E00#), Volatile;

      ITM_TPR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_0E40#), Volatile;

      DEMR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_EDFC#), Volatile;

      TPIU_SPP : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E004_00F0#), Volatile;

      TPIU_FFCR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E004_0304#), Volatile;

      TPIU_ACPR : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E004_0010#), Volatile;

      DWT_CTRL : Interfaces.Unsigned_32
        with Address => System'To_Address (16#E000_1000#), Volatile;

      use Interfaces;

   begin
      --  Enable write access via the Lock Access Register.
      ITM_LAR := 16#C5AC_CE55#;
      --  Enable the ITM, enable SWO mode behavior, enable synchronization
      --  packets, enable DWT event submission, enable timestamps.
      ITM_TCR := 16#0001_001F#;
      --  Enable access in user mode to all 32 channels.
      ITM_TPR := 16#0000_0000#;
      --  Enable all 32 trace channels.
      ITM_TER := 16#FFFF_FFFF#;

      --  Set TRCENA bit to 1 in Debug Exception and Monitor Register.
      DEMR := DEMR or 16#0100_0000#;

      --  Select NRZ serial wire output.
      TPIU_SPP := 16#0000_0002#;

      --  Deactivate formatter.
      TPIU_FFCR := 16#0000_0100#;

      --  Set prescalar (/10).
      --  TPIU_ACPR := 16#0000_0009#;

      --  Set prescalar (/15).
      TPIU_ACPR := 14;

      --  Enable exception trace and exception overhead.
      DWT_CTRL := DWT_CTRL or 16#0005_0000#;

   end Initialize;

   procedure Put (Channel : Channel_Type;
                  Value   : Value_Type) is
      Port_Reg : Value_Type with Address => System'To_Address (16#E000_0000#) +
        4 * Channel_Type'Pos (Channel), Volatile;
   begin
      --  Port register lsb is set when the the FIFO can accept at least one
      --  word.
      while Port_Reg = 0 loop
         null;
      end loop;
      Port_Reg := Value;
   end Put;

   procedure Put (Channel : Channel_Type;
                  Message : String) is
      Port_Reg : Value_Type with Address => System'To_Address (16#E000_0000#) +
        4 * Channel_Type'Pos (Channel), Volatile;
   begin
      --  Port register lsb is set when the the FIFO can accept at least one
      --  word.
      for Index in Message'Range loop
         while Port_Reg = 0 loop
            null;
         end loop;
         Port_Reg := Value_Type (Character'Pos (Message (Index)));
      end loop;
   end Put;

end SAM4S.Trace;
票数 6
EN

Stack Overflow用户

发布于 2015-07-29 06:11:12

当您用“逻辑分析器”标记它时,这可能是不主题,但我发现下面的内容非常有用。使用Keil uVision (可能还有其他IDE),您可以使用自定义.ini文件将ITM数据重新路由到文件中。

在调试器中启用SWJ,使用SW端口。启用跟踪,启用要使用的刺激端口。

编写一个具有如下内容的.ini文件:

代码语言:javascript
复制
ITMLOG 0 > "debug.log"
ITMLOG 1 > "testlog.xml"

这将将ITM通道0重新路由到名为"debug.log“的文件,将通道1重路由到"testlog.xml”(来自here的文件语法)。

为了方便地使用c代码中的fprinf通道,我使用以下设置:

代码语言:javascript
复制
struct __FILE { int channel; };
#include <stdio.h>

#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))

#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA          0x01000000

int fputc(int ch, FILE *f) {
  if (DEMCR & TRCENA) {
    while (ITM_Port32(f->channel) == 0);
    ITM_Port8(f->channel) = ch;
  }
  return(ch);
}

以及在项目中的使用:

代码语言:javascript
复制
FILE debug_stream = { .channel = 0 };
FILE test_stream = { .channel = 1 };

int main(void) {
    fprinf(&debug_stream, "this is a debug message, it will be rerouted to debug.log");
    fprinf(&test_stream, "this is a test message, it will be placed in testlog.xml");
}

参考资料:link

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32123443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档