问题描述
I would like to capture, decode, and view ITM trace information for a Cortex-M4 MCU (in my case, an Atmel SAM4S). In particular, I want to capture exceptions and user trace data relative to other signals on my board (i.e. show all signals and trace information on same timeline).
This can be done using the following steps:
- Place debugger in SWD mode. If using J-Link Segger on Linux, this can be done with
JLinkGDBServer -if swd
- Add code to the MCU to enable trace. Set the bit rate to a value suitable for your needs (I used 8 MHz). Example Ada code is below.
- Use logic analyzer to capture trace data on TRACESWO line from SAM4S processor. I used a Saleae Logic Pro 16 with 100 MHz sample rate.
Convert the data to a format usable by sigrok. Using the Saleae to capture the data, this comprises the following steps:
- 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
- Open the
trace.sr
file in PulseView. - Add UART decoder to TRACESWO channel, bit rate 8000000.
- Stack ARM-ITM decoder.
See http://www.sigrok.org/blog/new-protocol-decoders-arm-tpiu-itm-etmv3 for more information.
Example Ada code for SAM4S Trace:
sam4s-trace.ads:
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:
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;
这篇关于如何在 Cortex-M4 MCU 上捕获和查看 ITM 跟踪信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!