hi,
This is a request for comments for adapting arm coresight tracing in openocd.
It is motivated by :
- Current implementation of CoreSight tracing on ARM was developed for
ARM7, ARM9 and ARM11. this is now outdated and few developers are using it.
- Currently, there is an ongoing work on GDB to use CoreSight ETM traces
to provide branch traces (btrace). This will offer instructions and functions
histories, as well as execution record and replay in forwards and backwards
direction.
This RFC is to discuss upgrading Support for ARM CoreSight tracing to:
- Support interfacing with GDB for using the ETM traces
- Support saving traces in a file
- Support streaming traces to the TCL server
Current status:
- ETM IP configuration is outdated: On Cortex devices, access to CoreSight
trace IPs (ETM, ITM ...) is not done directly through JTAG anymore, but rather
though MEM-AP
- ETM traces parsing is outdated: it is not compatible with ETMv3 and ETMv4
Proposal:
- Provide device discovery with three classes of CoreSight tracing
devices: trace sources (ETM, PTM, ITM..), trace links (funnels) and trace sinks
(ETB, TMC, TPIU ...) with well defined interfaces for using them.
- Provide two ways for collecting the traces: though MEM-AP for internal
sinks (ETB, TMC) and through TPA (traces port analyzer) for external sinks
(TPIU) with well defined interfaces for using them.
- Provide a mean for specifying what to do with the traces ( use in GDB,
save to a file, steam to TCL server).
This will imply:
- Creating dedicated "drivers" for ITM IP, ETMv3 IP, ETMv4 IP, Funnel IP,
ETB IP, TMC IP and TPIU IP resp cs_itm.c, cs_etmv3.c, cs_etm_v4.c, cs_funnel.c, cs_etb.c,
cs_tmc.c, cs_tpiu.c.
- Update drivers for collecting traces either though MEM-AP or through TPA
(trace port analyzer).
- Creating needed commands for configuring the IPs in order to use them
and integrate them in the targets configuration scripts.
- Create a driver for TPA
User interface
GENERIC CORESIGHT DEVICES
- arm-cs-device create device_name -target target_name -dap dap_name
-ap-num apn -baseaddr base_address -type type : create a coresight device, with
generic coresight registers only
- arm-cs-device init : initialize coresight devices. detect device type,
append device specific register and assign device operations and context
- arm-cs-device list: list coresight devices with their dap names, ap,
base addresses and types
- arm-cs-device path (add|remove) device_name: add or remove a device to
trace path, the order is important since it will be followed in the
enable/disable order. it should be sources then links then sinks
- arm-cs-device path list : list the devices in trace path.
- cs-device_name dump: dumps the registers of a cs device.
Device specific commands
ETM
- etm_name info: gives info about the etm block, version, IP
configuration and availability of features.
- etm_name status: gives the status of the etm block (started, stopped,
current config etc..)
- etm_name config -trace_id trace_id [type context_id_bits cycle_accurate
timestamp ...] : change the configuration of etm, the list can be extended as
needed to support traces filtering and triggering.
- etm_name start : applies the configuration to the hardware and starts
emitting etm traces.
- etm_name stop : stop emitting etm traces.
ITM
- itm_name info: gives info about the itm block, version, IP configuration
and availability of features.
- itm_name status
- itm_name config -trace-id trace_id -enable-port port_number
-disable-port port_number -timestamp-prescaler prescaler -enable-dwt (on|off)
-enable-sync (on|off) -sync-count sync_count etc...
- itm_name start : start emitting itm traces
- itm_name stop : stop emitting itm traces
ETB
- etb_name info: gives info about the etb block, version, IP configuration
and availability of features.
- etb_name status
- etb_name start : start collecting CoreSight traces
- etb_name stop : stop collecting CoreSight traces
TPIU
- tpiu_name info : gives info about the tpiu block, version, IP
configuration and availability of features.
- tpiu_name status
- tpiu_name config -pin_protocol (parallel| manchester | nrz) -port_size
port_size -formatter (0|1) -prescaler prescaler -pin_frequency pin_frequency
etc ...
- tpiu_name start : start collecting CoreSight traces
- tpiu_name stop : stop collecting CoreSight traces
other devices
TPA
- tpa info
- tpa status
- tpa config -pin_protocol (parallel| manchester | nrz) -port_size
port_size -pin_frequency pin_frequency -mode (streamed|buffered)
- tpa start
- tpa stop
N.B. config commands modify internal context values. The configuration will be
applied to the hardware in the next start command
Traces processing
CS_TRACES
- cs_traces output -file filename -tcl_trace -socket port -gdb : set the
destination of collected traces
- cs_traces read -poll (on|off): set traces reading policy (continuous
polling vs on demand)
Software interfaces
Generic interface for coresight device drivers
struct arm_cs_device {
target_addr_t base;
struct adiv5_ap *ap;
};
enum arm_cs_device_type {
DEV_UNKNOWN, /**< Unknown device */
DEV_ROM, /**< ROM TABLE */
DEV_ETM, /**< ETM (v3 or v4), or PTM */
DEV_ITM, /**< ITM - Software trace stimulus */
DEV_STM, /**< STM - Software trace stimulus */
DEV_FUNNEL, /**< Trace Funnel */
DEV_REPLICATOR, /**< Trace Replicator */
DEV_ETF, /**< Embedded Trace FIFO - Trace memory controller in ETF
mode. */
DEV_ETB, /**< Embedded Trace Buffer - legacy trace buffer or TMC in
ETB/ETR */
DEV_TPIU, /**< Trace Port Interface - external interface to trace
system */
DEV_SWO, /**< Serial Wire Output */
DEV_CTI, /**< Cross Trigger Interface*/
DEV_CPU_DEBUG, /**< Core Debug registers */
DEV_CPU_PMU, /**< Core PMU registers */
DEV_TS, /**< Timestamp generator */
DEV_ELA, /**< Embedded logic analyzer */
DEV_MAX /**< End of type list */
};
struct arm_cs_device_object;
struct arm_cs_device_ops {
int (*init) (struct arm_cs_device_object * self); //initialize a cs device
int (*configure) (uint32_t what, void * value, struct arm_cs_device_object
* self); //change the context of the device with new configuration parameters
int (*start) (struct arm_cs_device_object * self); //apply configuration
and start tracing
int (*stop) (struct arm_cs_device_object * self); //stop tracing
int (*status) (struct arm_cs_device_object * self); //get tracing status
int (*read_traces) (struct arm_cs_device_object * self); //retrieve the
traces
};
#define CS_DEVICE_MAX_OFFSET (0xFFFFFFFF)
struct arm_cs_device_reg_cache{
uint32_t offset;
const char *label;
uint32_t value;
};
struct arm_cs_device_object {
struct list_head lh; //head of the devices list.
struct arm_cs_device cs_device; // to hold info relevant for accessing the
device.
int ap_num; // ap number for accessing this device.
char *name; //name of the device, it will be used afterward for issuing
commands to the device.
enum arm_cs_device_type cs_device_type; //type of the device (etm, itm,
funnel, etb, tpiu etc ...).
struct arm_cs_device_ops *cs_device_ops; // pointer to the implementation
of the operations on the device.
struct arm_cs_device_reg_cache *reg_cache; // cache of device registers
this a pointer to an array ending with a CS_DEVICE_MAX_OFFSET entry.
void *context; // device specific structure to hold the configuration and
the state of the device.
};
/** Writes a value to register at a given offset from device base address.
* write is using mem-ap to access the device */
extern int arm_cs_device_write_reg(struct arm_cs_device_object *self, unsigned
int offset, uint32_t value);
/** Reads a value from register at a given offset from device base address.
* read is using mem-ap to access the device */
extern int arm_cs_device_read_reg(struct arm_cs_device_object *self, unsigned
int offset, uint32_t *value);
/** Unlocks a CoreSight device. */
extern int arm_cs_device_unlock(struct arm_cs_device_object *self);
/** Locks a CoreSight device. */
extern int arm_cs_device_lock(struct arm_cs_device_object *self);
/** registers arm cs device commands to the openocds command list. */
extern int arm_cs_register_commands(struct command_context *cmd_ctx);
/** append a device specific registers to the generic coresight registers. */
extern int arm_cs_append_register_cache(struct arm_cs_device_object *self,
struct arm_cs_device_reg_cache *cache_template);
Your feedback and comments are welcome.
Kind Regards
Zied Guermazi