Serial Wire Debug¶
Serial Wire Output (SWO) alongside Serial Wire Debug (SWD) allows for the CPU
to emit real-time trace data. In particular, when used with an Instrumentation
Trace Macrocell (ITM), it can be used to form a Serial Wire Viewer (SWV). The
ITM ports are provided by the ARM controller. The SWV typically implements a
form of printf style debugging for embedded systems.
Getting Started¶
First, get your J-Link set up by instantiating an instance of a JLink and
connecting to your target device. Once that is established, you want to call
either swo_start():
speed = 9600
jlink.swo_start(swo_speed=speed)
or call swo_enable():
swo_speed = 9600
cpu_speed = 72000000 # 72 MHz
port_mask = 0x01
jlink.swo_enable(cpu_speed, swo_speed, port_mask)
Once enabled, you can begin reading data from the target.
Serial Wire Methods¶
-
class
pylink.jlink.JLink(lib=None, log=None, detailed_log=None, error=None, warn=None, unsecure_hook=None, serial_no=None, ip_addr=None, open_tunnel=False) Python interface for the SEGGER J-Link.
This is a wrapper around the J-Link C SDK to provide a Python interface to it. The shared library is loaded and used to call the SDK methods.
-
swd_read16(*args, **kwargs) Gets a unit of
16bits from the input buffer.Parameters: - self (JLink) – the
JLinkinstance - offset (int) – the offset (in bits) from which to start reading
Returns: The integer read from the input buffer.
- self (JLink) – the
-
swd_read32(*args, **kwargs) Gets a unit of
32bits from the input buffer.Parameters: - self (JLink) – the
JLinkinstance - offset (int) – the offset (in bits) from which to start reading
Returns: The integer read from the input buffer.
- self (JLink) – the
-
swd_read8(*args, **kwargs) Gets a unit of
8bits from the input buffer.Parameters: - self (JLink) – the
JLinkinstance - offset (int) – the offset (in bits) from which to start reading
Returns: The integer read from the input buffer.
- self (JLink) – the
-
swd_sync(*args, **kwargs) Causes a flush to write all data remaining in output buffers to SWD device.
Parameters: - self (JLink) – the
JLinkinstance - pad (bool) –
Trueif should pad the data to full byte size
Returns: None- self (JLink) – the
-
swd_write(*args, **kwargs) Writes bytes over SWD (Serial Wire Debug).
Parameters: - self (JLink) – the
JLinkinstance - output (int) – the output buffer offset to write to
- value (int) – the value to write to the output buffer
- nbits (int) – the number of bits needed to represent the
outputandvalue
Returns: The bit position of the response in the input buffer.
- self (JLink) – the
-
swd_write16(*args, **kwargs) Writes two bytes over SWD (Serial Wire Debug).
Parameters: - self (JLink) – the
JLinkinstance - output (int) – the output buffer offset to write to
- value (int) – the value to write to the output buffer
Returns: The bit position of the response in the input buffer.
- self (JLink) – the
-
swd_write32(*args, **kwargs) Writes four bytes over SWD (Serial Wire Debug).
Parameters: - self (JLink) – the
JLinkinstance - output (int) – the output buffer offset to write to
- value (int) – the value to write to the output buffer
Returns: The bit position of the response in the input buffer.
- self (JLink) – the
-
swd_write8(*args, **kwargs) Writes one byte over SWD (Serial Wire Debug).
Parameters: - self (JLink) – the
JLinkinstance - output (int) – the output buffer offset to write to
- value (int) – the value to write to the output buffer
Returns: The bit position of the response in the input buffer.
- self (JLink) – the
-
swo_enable(*args, **kwargs) Enables SWO output on the target device.
Configures the output protocol, the SWO output speed, and enables any ITM & stimulus ports.
This is equivalent to calling
.swo_start().Note
If SWO is already enabled, it will first stop SWO before enabling it again.
Parameters: - self (JLink) – the
JLinkinstance - cpu_speed (int) – the target CPU frequency in Hz
- swo_speed (int) – the frequency in Hz used by the target to communicate
- port_mask (int) – port mask specifying which stimulus ports to enable
Returns: NoneRaises: JLinkException– on error- self (JLink) – the
-
swo_flush(*args, **kwargs) Flushes data from the SWO buffer.
After this method is called, the flushed part of the SWO buffer is empty.
If
num_bytesis not present, flushes all data currently in the SWO buffer.Parameters: - self (JLink) – the
JLinkinstance - num_bytes (int) – the number of bytes to flush
Returns: NoneRaises: JLinkException– on error- self (JLink) – the
-
swo_num_bytes(*args, **kwargs) Retrives the number of bytes in the SWO buffer.
Parameters: self (JLink) – the JLinkinstanceReturns: Number of bytes in the SWO buffer. Raises: JLinkException– on error
-
swo_read(*args, **kwargs) Reads data from the SWO buffer.
The data read is not automatically removed from the SWO buffer after reading unless
removeisTrue. Otherwise the callee must explicitly remove the data by calling.swo_flush().Parameters: - self (JLink) – the
JLinkinstance - offset (int) – offset of first byte to be retrieved
- num_bytes (int) – number of bytes to read
- remove (bool) – if data should be removed from buffer after read
Returns: A list of bytes read from the SWO buffer.
- self (JLink) – the
-
swo_read_stimulus(*args, **kwargs) Reads the printable data via SWO.
This method reads SWO for one stimulus port, which is all printable data.
Note
Stimulus port
0is used forprintfdebugging.Parameters: - self (JLink) – the
JLinkinstance - port (int) – the stimulus port to read from,
0 - 31 - num_bytes (int) – number of bytes to read
Returns: A list of bytes read via SWO.
Raises: ValueError– ifport < 0orport > 31- self (JLink) – the
-
swo_set_emu_buffer_size(*args, **kwargs) Sets the size of the buffer used by the J-Link to collect SWO data.
Parameters: - self (JLink) – the
JLinkinstance - buf_size (int) – the new size of the emulator buffer
Returns: NoneRaises: JLinkException– on error- self (JLink) – the
-
swo_set_host_buffer_size(*args, **kwargs) Sets the size of the buffer used by the host to collect SWO data.
Parameters: - self (JLink) – the
JLinkinstance - buf_size (int) – the new size of the host buffer
Returns: NoneRaises: JLinkException– on error- self (JLink) – the
-
swo_speed_info(*args, **kwargs) Retrieves information about the supported SWO speeds.
Parameters: self (JLink) – the JLinkinstanceReturns: A JLinkSWOSpeedInfoinstance describing the target’s supported SWO speeds.Raises: JLinkException– on error
-
swo_start(*args, **kwargs) Starts collecting SWO data.
Note
If SWO is already enabled, it will first stop SWO before enabling it again.
Parameters: - self (JLink) – the
JLinkinstance - swo_speed (int) – the frequency in Hz used by the target to communicate
Returns: NoneRaises: JLinkException– on error- self (JLink) – the
-
swo_stop(*args, **kwargs) Stops collecting SWO data.
Parameters: self (JLink) – the JLinkinstanceReturns: NoneRaises: JLinkException– on error
-
swo_supported_speeds(*args, **kwargs) Retrives a list of SWO speeds supported by both the target and the connected J-Link.
The supported speeds are returned in order from highest to lowest.
Parameters: - self (JLink) – the
JLinkinstance - cpu_speed (int) – the target’s CPU speed in Hz
- num_speeds (int) – the number of compatible speeds to return
Returns: A list of compatible SWO speeds in Hz in order from highest to lowest.
- self (JLink) – the
-
Examples¶
Serial Wire Viewer¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | # -*- coding: utf-8 -*-
# Copyright 2017 Square, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Example Serial Wire Viewer.
#
# This module demonstrates implementing a Serial Wire Viewer using the PyLink
# library.
#
# Usage: swv.py jlink_serial_number device
# Author: Ford Peprah
# Date: Friday, September 23rd, 2016
# Copyright: 2016 Square, Inc.
import pylink
try:
import StringIO
except ImportError:
import io as StringIO
import string
import sys
import time
def serial_wire_viewer(jlink_serial, device):
"""Implements a Serial Wire Viewer (SWV).
A Serial Wire Viewer (SWV) allows us implement real-time logging of output
from a connected device over Serial Wire Output (SWO).
Args:
jlink_serial (str): the J-Link serial number
device (str): the target CPU
Returns:
Always returns ``0``.
Raises:
JLinkException: on error
"""
buf = StringIO.StringIO()
jlink = pylink.JLink(log=buf.write, detailed_log=buf.write)
jlink.open(serial_no=jlink_serial)
# Use Serial Wire Debug as the target interface. Need this in order to use
# Serial Wire Output.
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
jlink.connect(device, verbose=True)
jlink.coresight_configure()
jlink.set_reset_strategy(pylink.enums.JLinkResetStrategyCortexM3.RESETPIN)
# Have to halt the CPU before getitng its speed.
jlink.reset()
jlink.halt()
cpu_speed = jlink.cpu_speed()
swo_speed = jlink.swo_supported_speeds(cpu_speed, 10)[0]
# Start logging serial wire output.
jlink.swo_start(swo_speed)
jlink.swo_flush()
# Output the information about the program.
sys.stdout.write('Serial Wire Viewer\n')
sys.stdout.write('Press Ctrl-C to Exit\n')
sys.stdout.write('Reading data from port 0:\n\n')
# Reset the core without halting so that it runs.
jlink.reset(ms=10, halt=False)
# Use the `try` loop to catch a keyboard interrupt in order to stop logging
# serial wire output.
try:
while True:
# Check for any bytes in the stream.
num_bytes = jlink.swo_num_bytes()
if num_bytes == 0:
# If no bytes exist, sleep for a bit before trying again.
time.sleep(1)
continue
data = jlink.swo_read_stimulus(0, num_bytes)
sys.stdout.write(''.join(map(chr, data)))
sys.stdout.flush()
except KeyboardInterrupt:
pass
sys.stdout.write('\n')
# Stop logging serial wire output.
jlink.swo_stop()
return 0
if __name__ == '__main__':
exit(serial_wire_viewer(sys.argv[1], sys.argv[2]))
|