Skip to content
/ JtagDue Public
forked from rdiez/DebugDue

Emulates a Bus Pirate OpenOCD JTAG adapter with an Arduino Due

Notifications You must be signed in to change notification settings

dzcvk/JtagDue

 
 

Repository files navigation

JtagDue Project

The main goal of this project is to provide an up-to-date, comfortable bare-metal C++ programming environment for the Arduino Due and, in the future, for similar boards.

A secondary goal is to convert the Arduino Due into a JTAG adapter by emulating a Bus Pirate from Dangerous Prototypes , so that it is compatible with OpenOCD .

This means that you can use an Arduino Due (acting as a JTAG adapter) in order to debug with GDB your own code running on a second Arduino Due.

About the Bare Metal C++ Environment

The bare metal programming environment has the following features:

  • Event loop (super loop) architecture.

    The developer must manually call every library function and has therefore full control at any point in time.

    There are no OS background tasks or threads to worry about.

  • C++ exceptions.

  • Newlib with malloc support.

  • Assertions.

  • Debug console.

    Some useful generic commands are available: memory usage, CPU load in the last 60 seconds, compiler version used to build, last reset cause, uptime display, etc.

    Your code can write log messages to the console asynchronously, which means that normal execution carries on while the message characters are sent to the USB virtual serial port in the background (interrupt driven). If the background console output buffer overflows, console text will be lost, but the user will always see an indication that some text was lost at the position where the overflow occurred.

  • Library of common functions.

    Most basic functions you need to get started have been implemented: Busy wait loop helpers, basic text parsing, I/O utilities, stack usage tools, uptime calculation, a template-based circular buffer implementation, etc.

  • Start-up delay for easy JTAG debugging right after reset. This is useful for JTAG probes that do not support the RCLK signal (adaptive clock speed).

  • Firmware cross-compiled with the standard GCC and autotools.

About the JTAG Functionality

The Arduino Due has a faster USB port and a faster CPU, so it can easily outperform the Bus Pirate.

I made a quick test, and GDB's 'load' command reports a transfer rate of 24 KiB/s with the JtagDue firmware (release build) when programming a second JtagDue board, compared to 8 KiB/s with the Bus Pirate. When programming an STM32429I-EVAL1 evaluation board, which has an STM32F429 microcontroller, GDB reports 31 KiB/s compared to 24 KiB/s with its built-in SWD adapter, and I have obtained rates of around 84 KiB/s with an Atmel AT91SAM9G20-EK board when writing to SDRAM instead of Flash.

Note that I had to manually patch OpenOCD version 0.8.0 as of May 2013 in order for setting "buspirate_speed fast" to work with the Bus Pirate board, otherwise you have to revert back to "buspirate_speed normal", and then you get just 1 KiB/s when using the Bus Pirate as a JTAG adapter. If you modify OpenOCD in order to use bigger USB packets, you can reach slightly higher speeds with the JtagDue.

There are some caveats when using the Arduino Due with the JtagDue firmware as a JTAG adapter:

  • The JTAG interface can only handle 3.3 V signals.

  • There is no JTAG clock speed setting, just like the current Bus Pirate / OpenOCD combination (as of May 2013).

    The JTAG clock always runs at maximum speed, which may be too fast for some devices. I made some imprecise measurements, and the resulting TCK rate is around 3 MHz. This means there is no JTAG adaptive clocking support either.

  • The JTAG signals are driven by software and their timings are not clean.

    For example, TCK does not stay 50 % of the time high. The lowest-level JTAG bit shifting routine should be rewritten in assembly. Help in this area would be appreciated.

  • The Arduino Due pull-ups are too weak to be of any use, see comments about setting 'buspirate_pullup' below.

See this page for more information about my experience with the Arduino Due: http://www.devtal.de/wiki/Benutzer:Rdiez/ArduinoDue

Empty Firmware Project

There is an "EmptyFirmware" directory that generates a dummy firmware which performs minimal initialisation, prints some basic information (including the code and data size values explained below) to the Arduino Due's "programming" USB virtual serial port and then stops (it waits forever). This project exists for the following reasons:

1) The project can serve as a starting point for other projects.
2) With the Empty Firmware you can reliably stop the CPU over the JTAG interface.

That is the best way to measure OpenOCD and GDB transfer speeds or to stress-test the JTAG interface.

3) You can use this project to perform code size experiments.

The Empty Firmware is very small and you can easily see how much code size isolated features or components contribute to the final binary size.

You should get byte sizes similar to the following with an optimised build with asserts turned off:

Code size:             14,204
Initialised data size:  1,304
BSS size:               2,160
Total:                 17,668

This firmware also has C++ exception support, which automatically pulls in malloc() support from newlib.

Adding a call to sprintf() pulls in the corresponding formatting code from newlib and yields the following sizes:

Code size:             23,300
Initialised data size:  1,360
BSS size:               2,160
Total:                 26,820

That means an increase of 9,152 bytes the first time you touch a printf-style function.

Installation Instructions

Installing a binary file

Pre-built binary files are available in a separate repository at https://github.com/rdiez/JtagDueBinaries . These binaries can be flashed with the standard Arduino Due tools. Jump straight to section "Flash the new firmware" below in order to flash a pre-built binary file.

Building by hand

1) Build the toolchain (the GCC compiler for the Arduino Due).

Change to the 'Toolchain' subdirectory and type "make help" for more information.

2) Download and unpack the Atmel Software Framework into some directory of your choice.

I have tested against ASF version 3.19.0.95.

3) Build the JtagDue firmware for the Arduino Due like most Autotools projects:
a) Make sure the new toolchain's 'bin' subdirectory is in the PATH.

This is so that autoconf can find GCC etc. for the Arduino Due. You can check that the PATH is right manually by verifying that this command works:

arm-none-eabi-gcc --version
b) Run autogen.sh in the 'Project' subdirectory in order to generate the configure script.
c) Build the firmware. It is best to build out of the source tree like this:
mkdir obj
cd obj
../Project/configure --prefix=/some/bin/directory --with-atmel-software-framework=<directory where the ASF is>
make  --no-builtin-rules  -j $(( $(getconf _NPROCESSORS_ONLN) + 1 ))
make install

The binaries files land in the prefix directory you specified, inside a subdirectory called share . Look for files jtagdue.bin and emptydue.bin .

4) Flash the new firmware.

First of all, plug the USB cable into the Arduino Due's "programming" USB socket (as opposed to the "native" socket).

You will need the Bossac tool in order to download the firmware into the Arduino Due. The easiest way to get it is probably to install the official Arduino software environment. Usage example for Linux:

stty -F /dev/ttyACM0 1200 && bossac --port=ttyACM0 --force_usb_port=false --verify --write "filename.bin" --boot=1 --reset

Note that you need to leave the "/dev/" prefix out in the --port argument.

Alternatively, you could use the Arduino Due's JTAG port to download the firmware with GDB, but then you need some other JTAG adapter. I have used the Bus Pirate for that purpose.

5) Test whether the new firmware is working properly.

Plug the USB cable into the Arduino Due's "native" USB socket (as opposed to the "programming" socket).

If you are running Windows, you will be prompted the first time to install a driver for the new device, just point it to the "WindowsDriver" subdirectory. The .INF file in that subdirectory is actually just a special text file that associates JtagDue's USB IDs to Windows' own USB CDC driver, so that a standard "COMx" virtual serial port is automatically created upon connection. Unfortunately, you cannot choose a fixed serial port number (the "x" in the name), so that it will change from time to time depending on how many virtual serial ports currently exist on the system.

Linux and Mac OS do no need any drivers. On linux, a new virtual serial port device is automatically created with a name like "/dev/ttyACM0", just look for the right device name under the "/dev" directory.

Now you should be able to connect to the virtual serial port with your favorite serial port console emulator.

For example, this Linux client allows you to conveniently quit the client-side terminal emulator (the local 'socat' command) with Ctrl+C:

socat -t0  STDIO,raw,echo=0,escape=0x03  /dev/ttyACM0,b115200,cs8,parenb=0,cstopb=0,clocal=0,raw,echo=0,setlk,flock-ex-nb

On Windows, you can use Putty like this:

putty -serial COM8

The JtagDue firmware does not implement the usual command-line editing comfort features yet, like command history and all the standard cursor key movements.

Due to a protocol limitation, there is no welcome banner. Press the Enter key at least once to see the cursor ('>'), or type "help" for a list of available commands.

6) Find a way to address the JtagDue USB virtual serial port comfortably.

When you connect the Arduino Due to your Linux PC, you will get a new virtual serial port like /dev/ttyACM0 or /dev/ttyACM1, depending on how many serial ports currently exist on the system. If you wish to write your own scripts to automate JTAG tasks, it is desirable that the assigned device name is always the same.

The easiest way is to look under /dev/serial/by-id. Normally, when running the JtagDue firmware, you will automatically get a link like /dev/serial/by-id/usb-Arduino_Due_JTAG_Adapter_JtagDue1-if00, but the exact name may be different on your system. This link will stay the same even if you connect the Arduino Due to another USB port.

If you want to address your devices based on the USB port they are connected to, look under /dev/serial/by-path.

On many Linux systems, normal users do not have enough permissions to access USB virtual serial ports. In order to allow all users to access such ports, you will have to create a Linux udev rule. You can also specify a fixed name for a device, in order to get the same "/dev/jtagdue1" filename every time you connect your JtagDue-running Arduino Due.

The JtagDue firmware uses the standard Arduino Due Vendor ID, but uses a Device ID of 0x1234 (you can change it when configuring the build). It also reports a serial number of "JtagDue1". In order to get a fixed "/dev/jtagdue1" device name, create a new file called /etc/udev/rules.d/47-JtagDue.rules (as root) with the following content:

SUBSYSTEM=="tty" ATTRS{idVendor}=="2341" ATTRS{idProduct}=="1234" ATTRS{serial}=="JtagDue1" MODE="0666" SYMLINK+="jtagdue1"

You can also add an entry for the standard Arduino Due "programming" USB port. For example:

SUBSYSTEM=="tty" ATTRS{idVendor}=="2341" ATTRS{idProduct}=="003d" MODE="0666"

Restarting udev with "sudo restart udev" should not be necessary for the new rule file to be taken into account.

Theoretically, you can add a GROUP="some_group" option in order to restrict access to a particular user group, but I could not make it work on my system.

The next time you plug the Arduino Due, if it is running the JtagDue firmware, an entry like /dev/ttyACM1 will still be created, but there will also be a /dev/jtagdue1 link pointing to the right one.

If you are using the second example rule, you will not get a user-defined link, but the automatically-created links under /dev/serial/by-id and so on should now work for any user account.

7) Connect the JTAG pins to the target device.

You can see the JTAG signal pin numbers on the Arduino Due and their current state (as if they all were inputs) with command "JtagPins". This is the kind of output generated:

Input status of all JTAG pins:
TDI   (pin 42): high  |  GND2  (pin 43): low
 -    (pin 44):  -    |  nTRST (pin 45): high
TMS   (pin 46): high  |  nSRST (pin 47): high
TDO   (pin 48): high  |  VCC   (pin 49): high
TCK   (pin 50): high  |  GND1  (pin 51): low

That is the same pin layout as the 10-pin Altera USB Blaster connector, with some Atmel additions from the AVR JTAG header. Pin 1 on the USB Blaster (TCK) corresponds then to pin 50 on the Arduino Due.

If you are connecting to the JTAG interface of a second Arduino Due, the layout is different, look at the Arduino Due's schematic for details. You will probably need an adapter like Olimex' ARM-JTAG-20-10, because the JTAG header is smaller than usual, it has a 1.27 mm pitch (Samtec 0.05" micro header) instead of the normal 2.54 mm (0.1"). Power your target (second) Arduino Due by connecting its "programming" USB socket to your PC.

With the command above you can also verify that at least the ground signals (GND1 and GND2) are low and the VCC signal is high after connecting the JTAG cable.

In contrast to the Bus Pirate, the Arduino Due has no analog switch chip on board, so the VCC, GND1 and GND2 signals are _not_ used as reference voltages when driving the JTAG interface. You need to make sure beforehand that the voltage levels are the same on both the Arduino Due and the JTAG target board.

8) Connect to the JtagDue with OpenOCD.

First of all, you may need to build OpenOCD with support for the Bus Pirate. For example:

./configure --enable-buspirate --prefix="$HOME/SomeDir/openocd-0.8.0-bin"
make -j $(( $(getconf _NPROCESSORS_ONLN) + 1 ))
make install

You will need to disconnect the command console from the JtagDue's USB virtual serial port beforehand, if you have it open.

I have tested these instructions with OpenOCD version 0.8.0. Configure OpenOCD as if your JTAG adapter were a Bus Pirate, but bear in mind that:

  • Option 'buspirate_speed' has no effect, the USB transfer speed will always be the maximum available.

  • Option 'buspirate_vreg' has no effect, as the Arduino Due has no voltage regulator to supply power to other devices.

  • Option 'buspirate_pullup' only affects JTAG signals TDI, TDO, TCK and TMS, like in the Bus Pirate.

    The reset signals TRST and SRST are not affected (have no pull-up option).

    Note that the built-in pull-ups on the Atmel ATSAM3X8 are too weak (between 50 and 150 KOhm) to be of any use. On my dodgy test set-up, and once looked at TCK with the oscilloscope, and the rising edges were very long curves, the speed was not enough to run reliably at as low as 24 KHz.

  • If you set option 'buspirate_mode' to 'open-drain', JtagDue will use the Atmel ATSAM3X8's "Multi Drive Control" (Open Drain) mode.

    Therefore, you need to enable the internal pull-ups (which are probably too weak, see above) or have external ones in order to guarantee a high level on the lines when necessary.

  • Command 'buspirate_led' has no effect.

    The only LED on the Arduino Due is used as a heartbeat indicator at the moment.

From this point on, follow the standard OpenOCD instructions in order to connect to your target board.

If you are connecting to a second Arduino Due target, check out the files under OpenOCD/SecondArduinoDueAsTarget/ . You should be able to connect to it with a command like this:

cd <JtagDue root dir where this README file is>
openocd  --command "set JTAGDUE_SERIAL_PORT /dev/serial/by-id/usb-Arduino_Due_JTAG_Adapter_JtagDue1-if00"  -f "OpenOCD/SecondArduinoDueAsTarget/JtagDueInterfaceConfig.cfg"  -f "target/at91sam3ax_8x.cfg"  -f "OpenOCD/SecondArduinoDueAsTarget/OpenOCDJtagConfig.cfg"

If there are no errors, you should see at the bottom the following output:

Info : Buspirate switched to FAST mode
Info : Buspirate Interface ready!
Info : This adapter doesn't support configurable speed
Info : JTAG tap: sam3.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : sam3.cpu: hardware has 6 breakpoints, 4 watchpoints

Press Ctrl+C to quit OpenOCD at this point.

You may find it difficult to control your second Arduino Due over JTAG if it is not running the right kind of firmware. The reason is that, if the CPU is sleeping or not running at a high-enough frequency, the JTAG connection will not work well. Note also that the JtagDue firmware does not support adaptive JTAG clocking, which could help in this situation. If you hold the ERASE button for at least 220 ms on the target Arduino Due, you will experience this issue. OpenOCD will detect the JTAG chain correctly, but you will get errors like this if you try to connect over OpenOCD/JTAG with GDB:

Error: JTAG-DP OVERRUN - check clock, memaccess, or reduce jtag speed

After this error, any OpenOCD command like step is likely to fail with an error such as "target not halted".

The easiest way to overcome this problem is to flash the "EmptyFirmware" project (file emptydue.bin) with Bossac, see above for details. The EmptyFirmware, like the full JtagDue project, ramps up the CPU speed at the very beginning and then makes a short "busy" pause (without sleeping). This way, OpenOCD stands a good chance of connecting over JTAG right after resetting the board and stopping the CPU before the firmware runs too far away. The very early pause location enables you to debug comfortably most of the firmware initialisation sequence. You should use the same technique in your own firmware, or it will be hard (or maybe downright impossible) to debug it over JTAG.

9) Prepare a comfortable development environment.

First of all, make sure that script OpenOCD/SecondArduinoDueAsTarget/run-in-new-console.sh works fine on your system. You may have to install Konsole (KDE's terminal emulator) or amend the script to use some other terminal program. You can test it as follows:

./run-in-new-console.sh "echo Press ENTER... && read"

If everything works correctly, you should see a new console window asking you to press the ENTER key.

Then edit script JtagDueBuilder.sh, which lives next to this README file is. If you are programming a second Arduino Due over JTAG, you will have to make minimal modifications to routine user_config(). For other targets, you will have to make more amendments.

Try the modified script out with the following command:

./JtagDueBuilder.sh --clean --build --program --debug

That should build the firmware from scratch, send it to the target device and start debugging it.

The idea is that, no matter what development environment you are using (Emacs, Vim, Eclipse, ...), you should configure the usual compile/run/etc. keys to run the script with different arguments. For example:

F7 (compile):          ./JtagDueBuilder.sh --build
F5 (run)    :          ./JtagDueBuilder.sh --build --program --debug --debugger-type=ddd
Ctrl+Alt+F7 (rebuild): ./JtagDueBuilder.sh --clean --build
Ctrl+R (run to line):  ./JtagDueBuilder.sh --build --program --debug --add-breakpoint="Main.cpp:123"

This way, you will not have to type any console commands in order to run or debug your firmware. You will not get the full comfort you are used to when writing standard PC applications, but it will come close enough.

Still To Do

  • Stack Backtrace on Crash

    If the firmware crashes, I would like to get a call stack (a backtrace) on the debug console.

    On the PowerPC architecture, you can get a backtrace programmatically if I turn off GCC's stack frame optimisation. However, it looks like that is not easy to do on the ARM architecture. Or am I mistaken here? Is there perhaps a way to tell GCC to generate some sort of stack frame for this purpose?

    Otherwise, is it possible to dump the tip of the stack in such a way that a PC tool can then later on reconstruct the call stack, if the .elf file with debug information is available?

Changelog

  • Version 1.0.0, released on 11 may 2013, git tag "v1.0.0". First public version.

  • Version 1.1.2, released on 29 june 2014, git tag "v1.1.2". General improvement.

Feedback

Please send feedback to rdiezmail-arduino at yahoo.de

The project's official web site is https://github.com/rdiez/JtagDue

License

Copyright (C) R. Diez 2012, rdiezmail-arduino at yahoo.de

The source code is released under the AGPL 3 license.

Please note that some of the files distributed with this project may have other authors and licenses.

This document is released under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license.

About

Emulates a Bus Pirate OpenOCD JTAG adapter with an Arduino Due

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 69.4%
  • Shell 14.9%
  • Makefile 8.0%
  • C 7.2%
  • Assembly 0.5%