MIPI System Trace Module driver =============================== Copyright (C) ST-Ericsson SA 2011 Authors: Pierre Peiffer Philippe Langlais License: The GNU Free Documentation License, Version 1.2 (dual licensed under the GPL v2) Hardware overview ================= This hardware collects and provides simple tracepoints, so a system processor (in our case the main ARM CPU, or some small CPUs and DSPs) can write some data, up to 8 bytes, into a register and out comes a log entry with a time stamp (20ns resolution) on one of 256 channels. Also hardware tracepoints are supported. This module external interface is a pad on the chip which complies to the MIPI System Trace Protocol v1.0 (see http://www.mipi.org/specifications/debug) and the actual trace output can be read by an electronic probe, not by software so it cannot be intercepted by the CPU and reach Linux userspace. Bandwidth depends on number of lines & bus frequency (for example on ux500 SoC 4 lines at max 100MHz eg max 400Mbit/s shared between 7 cores). Transmit FIFO size: 256 samples up to 8 bytes. On ux500 platform there is 2 contiguous STM blocks (eg 512 channels) Software Overview ================= Write atomicity and write order on STM trace channels is ensured by the fact we try to allocate one channel by execution thread (no concurrent access). There is 2 modes one lossless but intrusive aka Software mode and another lossy mode less intrusive aka Hardware mode, by default all sources are configured in Hardware mode and enabled. The end of data packet is marked by a time stamp on latest byte(s) only. Kernel API ---------- Configuration functions: output trace clock frequency, trace mode, output port configuration and enable/disable STM trace sources Expose a debugfs interface too for STM trace control Alloc/free STM trace channel functions Set of low level atomic trace functions for 1, 2, 4 or 8 bytes with & w/o time stamp Higher level lockless trace functions: stm_trace_buffer: allocate a channel in 128 highest channels available output the trace buffer with arbitrary length (latest byte(s) automatically time stamped) then free the channel stm_trace_buffer_onchannel: use given channel to output the trace buffer with arbitrary length (latest byte(s) automatically time stamped) File IO output console like interface (open, close, write) See & drivers/misc/stm.c for more detail debugfs API ----------- clockdiv: This is used to set or display the current clock divisor that is configured connection: This is used to set or display the current output connector that is configured (common values, 0 not connected, 1 for default connection, 3 on Ux500 for APE MIPI34 connection) free_channels: This is used to display the total number of free channels masters_enable: This sets or displays whether the STM trace sources are activated. Each bits represent the state of corresponding source: 0 for disable or 1 to enable it. masters_modes: This sets or displays the STM trace sources modes. Each bits represent the mode of corresponding source: 0 for Sofware lossless mode or 1 for Hardware lossy mode. User API -------- IOCTLs or debugfs for controls 2 levels API for tracing: - Standard write function, in this case a channel is automatically allocated at first write, after you can channel number with IOCTL STM_GET_CHANNEL_NO - mmap for direct access of all STM trace channels port plus a set of IOCTLs for alloc/free channels, in this case you can write your own lib to easiest its usage Examples of using the STM ========================= First mount debugfs with: mount -t debugfs none /sys/kernel/debug In a shell scipt ---------------- It's as easy as: echo "My trace point" > /dev/stm To avoid trace overflow, increase STM clock by decreasing the clockdiv with: echo 1 >/sys/kernel/debug/stm/clockdiv # now use DIV2 instead of default DIV8 If not enough you can disable some sources with: echo YourEnableSources > /sys/kernel/debug/stm/masters_enable If always not enough the ultime intrusive way is to change the sources mode and set the corresponding sources in Software mode (set corresponding source bit to 0) with: echo YourModeSources > /sys/kernel/debug/stm/masters_modes (be aware some source doesn't support Software mode => keep it in HW mode) NB: on Ux500 platform, first you have to configure STM output port to switch APE tracing on MIPI34 connector with: echo 3 > /sys/kernel/debug/stm/connection In C language ------------- The easy way more intrusive (with STM buffer recopy): #include int fd, i; char buf[1024]; // Try to align this buffer on 64 bits if possible fd = open("/dev/stm", O_WRONLY); snprintf(buf, 1024, "STM0 Hello world\n"); write(fd, buf, strlen(buf)); ioctl(fd, STM_GET_CHANNEL_NO, &i); snprintf(buf, 1024, "Use channel #%d\n", i); write(fd, buf, strlen(buf)); close(fd); NB: You can call open("/dev/stm", O_WRONLY) as many times as necessary to allocate a different channel to avoid concurrency in your multithreaded application. The more efficient way, use mmap'ed STM channels memory (to put in a lib): #include int fd, i, c, l, maxChannels; char buf[1024]; // Try to align this buffer on 64 bits if possible volatile struct stm_channel *channels; // mmap'ed channels area fd = open("/dev/stm", O_RDWR); ioctl(fd0, STM_GET_NB_MAX_CHANNELS, &maxChannels); channels = (struct stm_channel *)mmap(0, maxChannels*sizeof(*channels), PROT_WRITE, MAP_SHARED, fd, 0); assert(channels != MAP_FAILED); if (!ioctl(fd, STM_GET_FREE_CHANNEL, &c)) { l = snprintf(buf, 1024, "STM0 Hello world on channel #%d\n", c); // lazy implementation you have to send buffer by 8 Bytes when possible // and be sure you don't share this channel with others threads for (i=0; i