Benutzer:Rdiez/ArduinoDue: Unterschied zwischen den Versionen

Aus /dev/tal
Wechseln zu: Navigation, Suche
(No Ethernet PHY)
(Several small fixes and improvements.)
Zeile 29: Zeile 29:
 
** No floating point support.
 
** No floating point support.
 
* 84 MHz clock frequency.
 
* 84 MHz clock frequency.
* 2 x 256 KBytes Flash.
+
* 2 x 256 KiB Flash.
* 64 + 32 KBytes RAM.
+
* 64 + 32 KiB RAM.
 
* The "native" USB port and can do High Speed USB 2.0 (480 Mbit/s).
 
* The "native" USB port and can do High Speed USB 2.0 (480 Mbit/s).
 
* JTAG port
 
* JTAG port
Zeile 184: Zeile 184:
 
   Leading bit:  1  # Always set to 1 according to the IEEE standard 1149.1
 
   Leading bit:  1  # Always set to 1 according to the IEEE standard 1149.1
  
Note that, if you connect the JTAG_RST signal and you JTAG probe holds it deasserted most of the time, the ATmega16U2 AVR microcontroller may no longer be able to trigger a reset when you connect to the 'Programming' USB serial port.
+
Note that, if you connect the JTAG_RST signal and you JTAG probe actively holds it high most of the time, the ATmega16U2 AVR microcontroller may no longer be able to trigger a reset when you connect to the 'Programming' USB serial port.
 +
 
 +
I read in OpenOCD's source file ''tcl/target/at91sam3XXX.cfg'' that the maximum JTAG speed for this kind of chip is F_CPU/6.
 +
If the CPU is running at the normal speed of 84 MHz, the maximum JTAG clock would be 14 MHz then.
 +
 
 +
The firmware must not use instruction WFE (Wait For Event), as this stops the CPU clock and breaks the JTAG connection.
  
 
If you abruptly disconnect the JTAG cable, you may leave breakpoints behind that, when triggered, will forever freeze the CPU. The JTAG logic on the CPUs does not normally detect the loss of the JTAG debugger, so always disconnect gracefully or reset the device after debugging.
 
If you abruptly disconnect the JTAG cable, you may leave breakpoints behind that, when triggered, will forever freeze the CPU. The JTAG logic on the CPUs does not normally detect the loss of the JTAG debugger, so always disconnect gracefully or reset the device after debugging.
Zeile 208: Zeile 213:
 
It may be possible to trigger a RSTC PROCRST from GDB or OpenOCD in order to reset the core and stop at the first instruction. Another way to stop the CPU right after a CPU reset could be flag C_SNAPSTALL in the "Debug Halting Control and Status" register at address 0xE000EDF0, but I haven't had time to check it out yet, please [[Benutzer:rdiez|drop me a line]] if you do.
 
It may be possible to trigger a RSTC PROCRST from GDB or OpenOCD in order to reset the core and stop at the first instruction. Another way to stop the CPU right after a CPU reset could be flag C_SNAPSTALL in the "Debug Halting Control and Status" register at address 0xE000EDF0, but I haven't had time to check it out yet, please [[Benutzer:rdiez|drop me a line]] if you do.
  
A good workaround is to add an initial delay in the firmware before it actually starts playing with the hardware, as the wrong I/O or system clock configuration could render the JTAG interface unusable. This way, there is a window of opportunity for a JTAG debugger to take control after a hardware reset, and you can debug most of the start-up sequence properly. The downside is that the boot process always takes a little longer, even if you are not debugging it.
+
A good workaround is to add an initial delay in the firmware before it actually starts playing with the hardware, as the wrong I/O or system clock configuration could render the JTAG interface unusable. This way, there is a window of opportunity for a JTAG debugger to take control after a hardware reset, and you can debug most of the start-up sequence properly. The downside is that the boot process always takes a little longer, even if you are not debugging it. The SAM3X starts at 4 MHz upon reset, so it is probably a good idea to ramp the clock up before the initial delay,
 +
so that you can use a fast JTAG clock right from the start.
  
 
== OpenOCD Reset Issues ==
 
== OpenOCD Reset Issues ==
Zeile 247: Zeile 253:
 
It is best to create separate configuration files for the JTAG adapter and for the Arduino Due board, so the OpenOCD command-line arguments look like this:
 
It is best to create separate configuration files for the JTAG adapter and for the Arduino Due board, so the OpenOCD command-line arguments look like this:
  
   openocd  -f your-jtag-adapter.cfg  -f target/at91sam3XXX.cfg  -f arduino-due.cfg
+
   openocd  -f your-jtag-adapter.cfg  -f target/at91sam3ax_8x.cfg  -f arduino-due.cfg
  
Configuration file ''target/at91sam3XXX.cfg'' comes with OpenOCD, so it should be able to find it automatically.
+
Configuration file ''target/at91sam3ax_8x.cfg'' comes with OpenOCD version 0.8.0, so it should be able to find it automatically.
 +
For older OpenOCD versions use file ''at91sam3XXX.cfg'' instead.
  
 
== Connecting with a Bus Pirate v3.5 ==
 
== Connecting with a Bus Pirate v3.5 ==
Zeile 255: Zeile 262:
 
=== Caveats ===
 
=== Caveats ===
  
The [http://dangerousprototypes.com/docs/Bus_Pirate Bus Pirate] is very slow as a JTAG adapter, you should expect speeds under 1 KB/s when downloading new firmware to the Arduino Due.
+
The [http://dangerousprototypes.com/docs/Bus_Pirate Bus Pirate] is very slow as a JTAG adapter, you should expect speeds under 1 KiB/s when downloading new firmware to the Arduino Due. If you manually patch OpenOCD version 0.8.0 so that setting "buspirate_speed fast" works, you can expect transfer rates of 8 KiB/s.
  
 
Firmware version v6.1 (current as of feb 2013) has a bug that might make you physically disconnect the USB cable often.
 
Firmware version v6.1 (current as of feb 2013) has a bug that might make you physically disconnect the USB cable often.
Zeile 266: Zeile 273:
 
I was surprised that just connecting the JTAG adapter powers the Bus Pirate, or at least the PWR LED turns on. Although it must be some partial current leakage, because connecting the USB cable makes the PWR LED shine brighter. The trouble is, that low current seems to be enough to keep the PIC running. Therefore, if you need to disconnect the Bus Pirate USB cable due to the bug described above, you will have to disconnect either the Arduino Due USB cable or the JTAG cable too.
 
I was surprised that just connecting the JTAG adapter powers the Bus Pirate, or at least the PWR LED turns on. Although it must be some partial current leakage, because connecting the USB cable makes the PWR LED shine brighter. The trouble is, that low current seems to be enough to keep the PIC running. Therefore, if you need to disconnect the Bus Pirate USB cable due to the bug described above, you will have to disconnect either the Arduino Due USB cable or the JTAG cable too.
  
OpenOCD cannot slow down the Bus Pirate's JTAG clock, which always runs at a fixed rate. I am not sure whether this limitation lies with OpenOCD or with the Bus Pirate firmware. The fixed clock rate becomes an issue if the SAM3X switches to its internal 32 KHz oscillator, which happens if your SAM3X firmware enters some power-saving mode. Note also that, upon reset, the CPU starts at 4 MHz, instead of the normal 84 MHz. When the CPU starts running at a lower frequency, you need to slow down the JTAG clock accordingly, or the JTAG connection will not work any more. This implies that you cannot debug the firmware from the beginning directly after a CPU reset with the Bus Pirate. You should also avoid in your firmware switching the SAM3X clock when idle.
+
The Bus Pirate firmware normally has the JTAG clock speed feature disabled, and the OpenOCD driver lacks the necessary support for it,
 +
therefore the OpenOCD cannot slow down the Bus Pirate's JTAG clock, which always runs at a fixed rate of around 750 Kbit/s.
 +
This fixed clock rate only becomes an issue if the SAM3X switches to its internal 32 KHz oscillator, which may happen if your SAM3X firmware enters some power-saving mode. You should avoid switching the SAM3X clock to a low frequency in your Arduino Due firmware if you plan to debug it over JTAG with the Bus Pirate.
  
 
=== Configuration File ===
 
=== Configuration File ===
Zeile 276: Zeile 285:
 
  buspirate_port /dev/buspirate
 
  buspirate_port /dev/buspirate
 
   
 
   
  # The 'fast' setting here does not work on my Ubuntu 12.04 PC, no idea if it would work elsewhere.
+
  # In order for the 'fast' setting to work you will probably need to manually patch OpenOCD (as of version 0.8.0).
 
  buspirate_speed normal  # 'normal' or 'fast'.
 
  buspirate_speed normal  # 'normal' or 'fast'.
 
   
 
   
Zeile 553: Zeile 562:
 
= Memory Map =
 
= Memory Map =
  
  0x0008 0000 - 0x0010 0000 512 Kbytes flash (2 consecutive banks)
+
  0x0008 0000 - 0x000B FFFF  256 KiB flash bank 0
  0x2000 0000 - 0x2000 FFFF  64 Kbytes sram0
+
  0x000C 0000 - 0x000F FFFF  256 KiB flash bank 1
  0x2007 0000 - 0x2007 FFFF  64 Kbytes mirrored sram0, so that it's consecutive with sram1
+
                            Both banks above provide 512 KiB of contiguous flash memory
  0x2008 0000 - 0x2008 7FFF  32 Kbytes sram1
+
  0x2000 0000 - 0x2000 FFFF  64 KiB SRAM0
 +
  0x2007 0000 - 0x2007 FFFF  64 KiB mirrored SRAM0, so that it's consecutive with SRAM1
 +
  0x2008 0000 - 0x2008 7FFF  32 KiB SRAM1
 
  0x2010 0000 - 0x2010 107F  4224 bytes of NAND flash controller buffer
 
  0x2010 0000 - 0x2010 107F  4224 bytes of NAND flash controller buffer
  

Version vom 6. Juni 2013, 19:43 Uhr

Warning sign
Dies sind die persönlichen Benutzerseiten von rdiez, bitte nicht verändern! Ausnahmen sind nur einfache Sprachkorrekturen wie Tippfehler, falsche Präpositionen oder Ähnliches. Alles andere bitte nur dem Benutzer melden!


Why the Arduino Due

This was my selection criteria:

  • Popular platform, well supported, reasonably priced.
  • Open-source hardware.
    Hopefully this will lead to lower prices and longer availability.
  • 32-bit CPU with good toolchain support.
    After having some negative experiences with GCC's PowerPC and AVR support, which are supposed to be stable after so many years of widespread usage, the ARM port looks much more polished.
  • High Speed (480 Mbps) USB tranfers (effective throughput up to 35 MB/s or 280 Mbit/s).
    This is about time, the USB 2.0 spec was released in April 2000 (!).
    Most ARM microcontrollers support only the 11 Mbit/s mode (as of 2013).

Other candidates:

  • The Beagle Bone was mostly sold out at the time.
  • The Raspeberry Pi is designed to act as an USB Host, and not as an USB Device.

Specs

The Arduino Due has a 144-pin AT91SAM3X8E microcontroller with the following features:

  • ARM Cortex-M3 core:
    • Implements the ARMv7-M architecture, which is a 32-bit architecture.
    • Supports all of the base Thumb-2 instruction set, where instructions can be 16-bit or 32-bit long.
    • Supports only Thumb-2, does not support the original 32-bit ARM instruction set.
    • Hardware multiplication and division.
    • Memory Protection Unit with 8 regions.
    • Limited support for unaligned memory accesses.
    • Choice of several modes with different privilege levels (user, supervisor...).
    • Support for single-bit atomic operations with (bit-banding)
    • No floating point support.
  • 84 MHz clock frequency.
  • 2 x 256 KiB Flash.
  • 64 + 32 KiB RAM.
  • The "native" USB port and can do High Speed USB 2.0 (480 Mbit/s).
  • JTAG port

Inadequate as a Learning and Hacking Platform

The Arduino Due is surprisingly inadequate as a learning and hacking platform:

  • The board comes with no "Getting Started" information whatsoever.
    The only piece of paper in the package sports some marketing blurb and tries to justify the price with statement "The people who made your board were reasonably paid". It should at least mention that you may want to load the blinking demo sketch, in order to check if the board is minimally working.
  • It is relatively expensive compared to more powerful platforms like the Rasperry Pi, the Beagle Bone and many of the microcontroller evaluation boards.
    Due to the low availability 4 months after release date I ended up paying 59 € for it, and that hurts if you manage to fry it during your experiments.
  • The development environment has no integrated debugger (!).
  • Launching a program, however small, takes a few seconds.
    That is quite a long time for such a modern board, it goes on your nerves. Maybe it is due to the beta development environment version 1.5.2 I tested, but why is it still beta? The release date was 22nd October 2012, more than 4 months ago.
  • It can only interface at 3.3 V level.
    The Bus Pirate v3.5 has a CD4066B analog switch that uses an external reference voltage.
    There are warnings all over the place that you can damage the board with a 5 V level, but why is there no protection circuitry? For hackers and learners such a safety feature would be a welcomed addition. How about some integrated 5 V capability too? With a small CPLD or FPGA you could probably choose your voltage level on a pin basis.
  • The board has a single user LED and no user buttons whatsoever, let alone any kind of display or sound ability.
    You need extra hardware for the most simple of tests.
  • There is no Ethernet connector, even though the microcontroller does support it. What is worse, there is no way to manually add an Ethernet PHY, because the right pins are simply not accessible.
  • Serious hackers will need a JTAG-based hardware debugger, which costs at least 50 €.
    There are some cheap USB-Blaster clones for 10 € in Ebay, but I haven't been able to make mine work properly yet.
    The Arduino designers added a separate 8-bit AVR CPU in order to update the main microcontroller firmware over the "programming" USB port. What a complete waste of time! They could have added some existing JTAG-over-USB chip, or they could have made one themselves by connecting that little AVR to the JTAG wires.
  • 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").
    Most hackers will have to pay extra for an adapter like Olimex' ARM-JTAG-20-10. If you have an Atmel JTAGICE3, look for an adapter in the box.
  • You'll probably need buy extra USB cables too.
    The board has 2 USB ports, the "native" USB socket is of type Micro-A, and the "programming" one is of type Micro-B. It may be my bad luck, but all devices I use have the Mini-B connector (Bus Pirate, USB-Blaster, AVR JTAGICE3, Wind River probe...), so I didn't have the right cable at hand. Of course there isn't one in the Arduino Due box either. Wasn't USB supposed to be standard? Apparently, there is a type of USB cable that fits in both Micro-A and Micro-B connectors, but the documentation offers no advice about this either. I wonder why there are 2 types of Micro USB connectors then, it's just confusing. To top it all, both sockets have such a tight grip that I worry they will break or wear out soon if I need to plug and unplug USB cables often.
  • The supplied software library is of low quality and is poorly documented too.
    There is no provision for proper data communications between the host and the Arduino Due, the environment can only display console text. There are also nasty surprises, like the 128-byte (actually 127) buffer for outgoing serial communications over USB. There is no way to tell whether there is space left in the buffer before sending data (there is no flow control), so you may end up losing bytes without warning.
  • Linux issues:
    • The Linux installation instructions are not together in a single page.
    • If the Arduino environment does not detect any suitable port, all ports options are greyed out with not further explanation.
      Also, after selecting the Arduino Due in the Tools/Board menu, it was not clear which option to select under Tools/Programmer.
    • It was not clear that the reason why your account may need "dialout" privileges is because /dev/ttyACM0 belongs to that group. One web page stated "No driver installation is necessary for Linux.", but fails to mention that you will probably need to configure things manually. I tried the suggested "sudo usermod", but it took me a while to realise that this change does not take place immediately. You probably don't have to restart the PC, but that is what I tried, and it did the trick.
    • There is no Ubuntu or Debian package that remembers where it came from and updates itself automatically, like Jitsi or VirtualBox do.
    • Atmel (the CPU manufacturer) offers little Linux support and tends to keep JTAG debugging documentation secret.

Reset Handling

SAM3X Reset

The SAM3X performs a reset in the following situations:

  • Power-up.
  • The user presses the RESET button.
    This asserts the MASTER-RESET signal, which also goes to the RESET pin next to the 3.3V and 5V reference voltage pins.
    Note that this does NOT reset the ATmega16U2 AVR microcontroller, so that the 'Programming' USB connection is not affected.
  • The ATmega16U2 presses the RESET button (virtually) every time you connect to the 'Programming' USB serial port.
    Under Linux, setting the port speed with command "stty -F /dev/ttyACM0 115200" is enough to trigger the reset. Note that the 1200 bps speed triggers an 'erase' procedure, see below.
  • A JTAG debugger can assert the JTAG_RESET signal, which is connected to MASTER-RESET too.
  • The firmware can request a reset with NVIC SYSRESETREQ, RSTC PROCRST and the like.

On reset, the SAM3X CPU looks at flag GPNVM1:

  • If GPNVM1 is 0, the CPU runs the built-in SAM-BA bootloader.
  • If GPNVM1 is 1, the CPU runs the user's firmware from flash memory.

Last Resort Rescue Button

In order to avoid 'bricking' the SAM3X CPU by flashing a defective firmware, there is an ERASE pushbutton on the board, which deletes the whole flash memory and clears the GPNVM1 bit. Note that you need to hold the button for at least 220 ms (see the AT91SAM3X8E datasheet).

Such a "last resort" hardware solution is necessary for the following reasons:

  • You may not have a JTAG probe at hand.
  • The firmware may disable the JTAG interface in order get more standard I/O pins, or reconfigure it as a Serial Wire debug interface.
  • The firmware may switch to the internal 32 KHz oscillator, or may keep changing the system clock in a tight loop. Depending on your JTAG probe, this might hinder the JTAG connection.

The small ATmega16U2 AVR microcontroller on the Arduino Due also presses the ERASE button (virtually) when you configure the serial interface over the 'Programming' USB port to 1200 bps, see below for more information.

Note that the user firmware can reconfigure the ERASE / PC0 pin as a general-purpose I/O. I did not want to risk my board, so I am not sure if you could rescue it afterwards by say holding down the RESET and ERASE buttons at the same time. Therefore, you should generally avoid reconfiguring PC0 in order to prevent confusion (at least). If worse comes to worst, you may find some pointers in section "Entering Programming Mode" on the AT91SAM3X8E datasheet.

SAM-BA Bootloader

On start-up, the built-in SAM-BA bootloader performs some minimal SAM3X configuration (like setting the system clock) and waits for a serial connection over the first UART interface or over USB, whichever comes first.

Note that the SAM-BA bootloader resides in an internal ROM and cannot be modified. Its code is secret, as it implements the firmware security feature, and cannot be seen or stepped through with a JTAG debugger.

USB Ports

The SAM3X's first UART interface (RX is PA8, TX is PA9) is connected to the ATmega16U2 AVR microcontroller, which acts as a USB-to-serial converter. The corresponding USB port is labelled as "PROGRAMMING" on the board's backside. The serial port connection parameters do matter, always use 115200 8N1 when connecting to SAM-BA. If you set the serial port speed to 1200 bps, the ATmega16U2 will trigger an ERASE procedure on the SAM3X. Under Linux, you can achieve that with command "stty -F /dev/ttyACM0 1200". Note that connecting at 1200 bps with 'picocom' does not seem to trigger the ERASE, but conneting with 'minicom' does (?).

The SAM3X's USB port is labelled as "NATIVE". The serial port connection parameters do not actually matter for this port, as transfers are always performed at the maximum USB speed available. However, if your firmware uses the standard Arduino libraries, configuring the 'Native' serial port to a speed of 1200 bps will trigger an ERASE procedure. You cannot rely on this method in real life, for it will no longer work if your firmware crashes or freezes.

The above means that you can talk to the SAM-BA bootloader on any of the 2 USB ports on the Arduino Due. Having 2 such ports does not actually make a lot of sense, see section "Inadequate as a Learning and Hacking Platform" above for more information. The 'Programming' USB port is more convenient if your firmware uses it as a logging console, because its associated serial port does not close when you manually reset the SAM3X CPU with the RESET button. Keep in mind that just connecting to that serial port will trigger an initial reset. The 'Native' USB port is faster, but, unless your firmware waits for a USB connection on start-up (for example, with "while (!SerialUSB);"), you will lose the first log messages, because the serial port will close on reset and you will have to reconnect after the firmware is already running.

The SAM-BA Protocol

The bootloader understands a very simple procotol with a few commands to read from and write to memory addresses. Atmel supplies a GUI tool that understands this protocol, and the Arduino environment comes with an open-source, command-line tool called 'bossac' to that effect.

In order to test the SAM-BA communication, press the ERASE button on the board for at least 220 ms, connect to one of the USB ports and issue the following command:

 bossac --port=ttyACM0 --info

On my Arduino Due, I get the following information:

 Device       : ATSAM3X8
 Chip ID      : 285e0a60
 Version      : v1.1 Dec 15 2010 19:25:04
 Address      : 524288
 Pages        : 2048
 Page Size    : 256 bytes
 Total Size   : 512KB
 Planes       : 2
 Lock Regions : 32
 Locked       : none
 Security     : false
 Boot Flash   : false

You can actually type SAM-BA commands manually. For example:

 picocom -b 115200 -p n -d 8 /dev/ttyACM0
 # Type 'T' (in uppercase) and then '#' to enter Terminal Mode.
 # Type 'V (in uppercase) and then '#' to display version information.
 # Type Ctrl+A, Ctrl+X in oder to exit picocom.

On my Arduino Due, the version information displayed with this method is:

 v1.1 Dec 15 2010 19:25:04

Firmware Update

Downloading with the Arduino environment

This is what happens when you click on the "Upload" button in the Arduino environment:

  1. The 'Programming' USB port gets opened with a speed of 1200 bps, which makes the ATmega16U2 trigger an 'erase' procedure on the SAM3X. The SAM3X boots then into SAM-BA and waits.
  2. The 'bossac' tool connects to SAM-BA over the ATmega16U2 with a speed of 115200 bps and performs the following steps:
    1. Erase the entire flash (unnecessary after the 'erase' procedure above, but it's very quick).
    2. Write the flash contents with the new firmware.
    3. Verify the flash contents (which is optional).
    4. Set the GPNVM1 bit to 1, so that the new firmware will boot upon reset (instead of the SAM-BA bootloader).
    5. Reset the SAM3X. The new firmware should start now.

With version 1.5.2 of the Arduino environment, you can only download the firmware over the 'Programming' USB interface. If you try to use the 'Native' USB port, you get a "No device found on ttyACM0" error message. However, you can then copy the 'bossac' command line from the build output window, remove the '-U false' argument, and run it on a command console, and then it works. It's also much faster than the 'Programming' USB port.

Downloading over JTAG

You can download new firmware to the SAM3X over JTAG with GDB and OpenOCD, just use GDB's 'load' command. GDB sets the $pc to the entry point, so just type 'continue' afterwards in order to start the new firmware. See below for more information about debugging over JTAG.

GDB understands the ELF file format and flattens it automatically upon firmware upload, but you probably want to generate a "bin" file as part of the standard makefile in order to be able to flash the board later on with the 'bossac' tool. Otherwise, you will have to connect the JTAG adapter every time you want to update the firmware.

How to Set the GPNVM1 bit

If you want the firmware to automatically run after a reset, you'll have to set the GPNVM1 bit to 1, see above for more information. There are several ways to do that:

  1. You can set the GPNVM bits with command "at91sam3 gpnvm" in OpenOCD.
    Run the 'bossac' tool with the '-d' argument in order to see the memory write sequence needed to set that bit from other environments.
  2. If you are connected with the 'Programming' USB interface, or you are connected with the 'Native' USB interface but your are using the Arduino libraries and the firmware works, or SAM-BA is already running:
    1. You can download your firmware with bossac, if you have generated the corresponding .bin file. Just append "--boot=1" to bossac the command line.
    2. You can download some example sketch with the Arduino environment. You will have to download your firmware over JTAG again.
    3. You can issue commands "stty -F /dev/ttyACM0 1200" and "bossac --port=ttyACM0 --boot=1".
      You will have to download your firmware over JTAG again, or the CPU will attempt to run the just-erased firmware upon reset.
  3. Otherwise, use the manual, fail-safe method:
    1. Hold the ERASE button for at least 220 ms.
    2. Press the RESET button, in case the SAM3X is running the just-erased firmware.
    3. Connect to any of the USB ports and issue command "bossac --port=ttyACM0 --boot=1".
      You will have to download your firmware over JTAG again, or the CPU will attempt to run the just-erased firmware upon reset.

Debugging over JTAG

Connecting over JTAG

When connected to the Arduino Due, OpenOCD discovers a JTAG IDCODE of 0x4BA00477. The JTAG Instruction Register has a length of 4 bits.

The IDCODE breakdown, using my script to decode JTAG IDCODEs, is as follows:

 Decoding of JTAG IDCODE 0x4BA00477 (1268778103, 0b01001011101000000000010001110111):
 Version:      0b0100  (0x4, 4)
 Part number:  0b1011101000000000  (0xBA00, 47616)
 Manufacturer: 0b01000111011  (0x23B, 571)  # Name: ARM Ltd.
 Leading bit:  1  # Always set to 1 according to the IEEE standard 1149.1

Note that, if you connect the JTAG_RST signal and you JTAG probe actively holds it high most of the time, the ATmega16U2 AVR microcontroller may no longer be able to trigger a reset when you connect to the 'Programming' USB serial port.

I read in OpenOCD's source file tcl/target/at91sam3XXX.cfg that the maximum JTAG speed for this kind of chip is F_CPU/6. If the CPU is running at the normal speed of 84 MHz, the maximum JTAG clock would be 14 MHz then.

The firmware must not use instruction WFE (Wait For Event), as this stops the CPU clock and breaks the JTAG connection.

If you abruptly disconnect the JTAG cable, you may leave breakpoints behind that, when triggered, will forever freeze the CPU. The JTAG logic on the CPUs does not normally detect the loss of the JTAG debugger, so always disconnect gracefully or reset the device after debugging.

Debugging from the start

Getting the initialisation code right in your firmware is often hard, so the capability to debug the start-up code out of a core reset can save a lot of time and frustration. It is also important that the system behaves exactly the same under the debugger as in real life, otherwise you may never be able to reproduce and debug a problem when connected with a JTAG probe. Unfortunately, the SAM3X controller on the Arduino Due falls short precisely in these areas, like many other microcontrollers I know.

Say you make your JTAG adapter toggle the JTAG_SRST signal as part of a "reset halt" command. This signal is connected to the MASTER-RESET signal on the board and to the SAM3X's NRSTB pin, and I have found out empirically that no JTAG communication can take place while that pin remains asserted, it looks like the JTAG logic gets reset too (but this is not clearly documented). When the reset is deasserted, the CPU immediately starts running the user firmware. However, it takes some time for OpenOCD to reconnect over JTAG and issue a CPU halt request. In the mean time, the firmware may have initialised and even used some peripherals. Once the CPU is stopped, you may issue a CPU core-only reset, or even reset all CPU peripherals, but you cannot assert the JTAG_SRST signal again. On the Arduino Due, pin NRST is not connected, and if any other peripherals (like Arduino shields) are connected to the MASTER-RESET signal, they will not get reset again before the CPU firmware starts the second time around. Therefore, you will not be able to debug the same start-up situation as during power-up or after a manual reset.

The key component missing is some sort of JTAG command like "reset the complete board and wait at the first instruction". Therefore, it is best to avoid using the MASTER-RESET signal on your designs, which means that you should not use the RESET pin available on the Arduino Board. In any case, it is generally good practice to keep all peripherals in reset mode until the firmware decides to activate them, preferrably one by one. If there are separate reset lines, the firmware can then selectively reset peripherals, should they get stuck.

The OpenOCD documentation states how the reset logic should work:

 In the best case, OpenOCD can hold SRST, then reset the TAPs via TRST and send
 commands through JTAG to halt the CPU at the reset vector before the 1st instruction
 is executed. Then when it finally releases the SRST signal, the system is halted under
 debugger control before any code has executed. This is the behavior required to support
 the "reset halt" and "reset init" commands.

You may think that it is possible to emulate a CPU core reset with a GDB script by setting the $pc, the stack pointer, disabling interrupts and so on. However, a real core reset may be necessary under certain circumstances. For example, the watchdog can only be programmed once in the firmware.

It may be possible to trigger a RSTC PROCRST from GDB or OpenOCD in order to reset the core and stop at the first instruction. Another way to stop the CPU right after a CPU reset could be flag C_SNAPSTALL in the "Debug Halting Control and Status" register at address 0xE000EDF0, but I haven't had time to check it out yet, please drop me a line if you do.

A good workaround is to add an initial delay in the firmware before it actually starts playing with the hardware, as the wrong I/O or system clock configuration could render the JTAG interface unusable. This way, there is a window of opportunity for a JTAG debugger to take control after a hardware reset, and you can debug most of the start-up sequence properly. The downside is that the boot process always takes a little longer, even if you are not debugging it. The SAM3X starts at 4 MHz upon reset, so it is probably a good idea to ramp the clock up before the initial delay, so that you can use a fast JTAG clock right from the start.

OpenOCD Reset Issues

The reset shortcoming described above becomes apparent when using OpenOCD, although OpenOCD itself seems to have additional issues too. The behaviour below was ascertained with OpenOCD version 0.7.0-dev, using configuration setting "reset_config srst_only srst_pulls_trst srst_open_drain".

If you type 'reset' on the OpenOCD console, the firmware starts twice, I tested it by printing a welcome banner in the firmware.

Manually pressing the RESET button on the Arduino Due confuses OpenOCD, the JTAG connection no longer works correctly. Command "scan_chain" continues to work, but "jtag init" does not. Issue a 'reset' command on the OpenOCD console to restore the JTAG connection.

Command 'reset halt' resets the CPU but cannot not stop the SAM3X afterwards. However, typing a 'halt' command afterwards does work. See routine "my_reset_and_halt" in my configuration file.

Furthermore, if the CPU is currently running, command 'soft_reset_halt' does reset the SAM3X but does not manage to halt it the first time around, and there is no error message at all. A second attempt does work, and this problem does not exist if the CPU was already halted. Nevertheless, the SAM3X does not stop at the first instruction after reset, but much further ahead. Reset config options "sysresetreq" and "vectreset" did not make any difference. When the SAM3X eventually stops, the CPU register values in GDB (including $pc) are out of sync with the ones displayed in the OpenOCD console (which are the correct ones), but there is a work-around, look for command "gdb_sync" in the OpenOCD help.

Hardware breakpoints tend to be ignored when resetting the CPU, even with 'soft_reset_halt'. Software breakpoints cannot be used anyway for firmware locations in flash memory.

On the other hand, command 'halt' seems to reliably stop the CPU in all situations, assuming that the JTAG connection is not broken.

OpenOCD performs a SAM3X reset on shutdown, which I wasn't expecting either.

Software Reset Sources

I have kept this section here for reference purposes.

Software reset sources are:

  • NVIC, which is described in the Cortex-M3 standard:
    • SYSRESETREQ is intended to force a large system reset of all major components except for debug, the actual behaviour is manufacturer specific.
      It is not entirely clear in the AT91SAM3X8E datasheet, but it looks like this triggers a RSTC PROCRST. I don't know whether the peripherals (RSTC PERRST) are affected.
    • VECTRESET resets the ARM core only, with the exception of debug components. When debugging, it should be issued when the core is halted.
  • RSTC, which is Atmel specific:
    • RSTC PROCRST resets the CPU core and watchdog.
    • RSTC PERRST resets the CPU peripherals only. Normally used together with PROCRST.
    • RSTC EXTRST asserts the NRST pin, which is not connected on the Arduino Due.

The Cortex-M3 core contains a CoreSight unit that manages the debug interfaces (JTAG, SWD, Trace, ...), so you may find more debugging information in CoreSight's documentation.

Starting OpenOCD

It is best to create separate configuration files for the JTAG adapter and for the Arduino Due board, so the OpenOCD command-line arguments look like this:

 openocd  -f your-jtag-adapter.cfg  -f target/at91sam3ax_8x.cfg  -f arduino-due.cfg

Configuration file target/at91sam3ax_8x.cfg comes with OpenOCD version 0.8.0, so it should be able to find it automatically. For older OpenOCD versions use file at91sam3XXX.cfg instead.

Connecting with a Bus Pirate v3.5

Caveats

The Bus Pirate is very slow as a JTAG adapter, you should expect speeds under 1 KiB/s when downloading new firmware to the Arduino Due. If you manually patch OpenOCD version 0.8.0 so that setting "buspirate_speed fast" works, you can expect transfer rates of 8 KiB/s.

Firmware version v6.1 (current as of feb 2013) has a bug that might make you physically disconnect the USB cable often. The bug title is "Issue 65: Binary Mode misbehaves after receiving 20 zeroes at once" and was reported here. If OpenOCD hangs or crashes, it will not be able to connect to the Bus Pirate again. The only work-around I found to date is to disconnect and reconnect the USB cable to the Bus Pirate. It also happens if you stop OpenOCD with Ctrl+C, because OpenOCD does not seem to properly shutdown the connection to the Bus Pirate upon receiving that signal. This is a major pain, because you need to telnet to OpenOCD on another window and issue a "shutdown" command in order to properly terminate OpenOCD every time. You can partially automate this with a command like this:

 echo shutdown | telnet localhost 4444

I was surprised that just connecting the JTAG adapter powers the Bus Pirate, or at least the PWR LED turns on. Although it must be some partial current leakage, because connecting the USB cable makes the PWR LED shine brighter. The trouble is, that low current seems to be enough to keep the PIC running. Therefore, if you need to disconnect the Bus Pirate USB cable due to the bug described above, you will have to disconnect either the Arduino Due USB cable or the JTAG cable too.

The Bus Pirate firmware normally has the JTAG clock speed feature disabled, and the OpenOCD driver lacks the necessary support for it, therefore the OpenOCD cannot slow down the Bus Pirate's JTAG clock, which always runs at a fixed rate of around 750 Kbit/s. This fixed clock rate only becomes an issue if the SAM3X switches to its internal 32 KHz oscillator, which may happen if your SAM3X firmware enters some power-saving mode. You should avoid switching the SAM3X clock to a low frequency in your Arduino Due firmware if you plan to debug it over JTAG with the Bus Pirate.

Configuration File

Remember to enable the Bus Pirate support when building OpenOCD, use the "--enable-buspirate" switch when configuring the build. This is the OpenOCD configuration file I am using at the moment:

interface buspirate

buspirate_port /dev/buspirate

# In order for the 'fast' setting to work you will probably need to manually patch OpenOCD (as of version 0.8.0).
buspirate_speed normal  # 'normal' or 'fast'.

# The Bus Pirate can supply power (3.3 V and 5 V) to an external circuit,
# but we do not need to power anything over JTAG.
buspirate_vreg 0  # voltage regulator: enabled = 1, disabled = 0

# There are two ways to configure the JTAG connection:
# 1) Connect JTAG_VREF and let the Bus Pirate use the target board's voltage.
#    - Set the mode to "open drain/open collector", which means high=Hi-Z, low=ground.
#    - Enable the pull-ups, which connects them to the target's JTAG_VREF,
#      effectively making high=JTAG_VREF.
#    This is the mode we are using at the moment, as it is also the safest.
# 2) Do not connect JTAG_VREF. The JTAG signals will be driven at 3.3 V.
#    - Set the mode to "normal", which means high=3.3 V, low=ground.
#    - Disable the pull-ups.
#    This would work for us too, as the Arduino Due's JTAG interface uses 3.3 V as well.
buspirate_mode open-drain  # 'normal' or 'open-drain'
buspirate_pullup 1  # pullup state: enabled = 1, disabled = 0

USB Information

The IDs for the 'Programming' USB interface are:

USB Vendor  ID: 0x2341 (Arduino)
USB Product ID: 0x003d ('Programming' USB interface)

The IDs above do not change unless you reprogram the 8-bit AVR firmware on the board, which is normally never the case.

The IDs for the 'Native' USB interface depend on the firmware running on the AT91SAM3X8E microcontroller:

If the board is running the Arduino firmware:

USB Vendor  ID: 0x2341 (Arduino)
USB Product ID: 0x003e ('Native' USB interface)

If you press the Erase button and the board is running Atmel's SAM-BA bootloader:

USB Vendor  ID: 0x03eb (Atmel)
USB Product ID: 0x6124 (SAM-BA)

lsusb -v Information for the 'Programming' USB Interface

Bus 001 Device 010: ID 2341:003d  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            2 Communications
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x2341 
  idProduct          0x003d 
  bcdDevice            0.01
  iManufacturer           1 Arduino (www.arduino.cc)
  iProduct                2 Arduino Due Prog. Port
  iSerial               220 7523230323535180A120
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           62
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0 
      CDC Header:
        bcdCDC               10.01
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval             255
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

lsusb -v Information for the 'Native' USB Interface

Note that if your firmware is not using the standard Arduino sketch library, you will get different values here.

Bus 001 Device 011: ID 2341:003e  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x2341 
  idProduct          0x003e 
  bcdDevice            1.00
  iManufacturer           1 Arduino LLC
  iProduct                2 Arduino Due     
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          100
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              500mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      0 None
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x01
          call management
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval              16
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.01
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     101
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  bNumConfigurations      1
Device Status:     0x0000
  (Bus Powered)

Memory Map

0x0008 0000 - 0x000B FFFF   256 KiB flash bank 0
0x000C 0000 - 0x000F FFFF   256 KiB flash bank 1
                            Both banks above provide 512 KiB of contiguous flash memory
0x2000 0000 - 0x2000 FFFF   64 KiB SRAM0
0x2007 0000 - 0x2007 FFFF   64 KiB mirrored SRAM0, so that it's consecutive with SRAM1
0x2008 0000 - 0x2008 7FFF   32 KiB SRAM1
0x2010 0000 - 0x2010 107F   4224 bytes of NAND flash controller buffer

The default vector table is at 0x0008 0000 (the start of flash):

  0x00080000 : initial stack pointer
  0x00080004 : firmware entry point address

For more information, look at section "embedded memories" in the AT91SAM3X8E datasheet.

Feedback

Some of the information on this page is pure guesswork. If you know better, please drop me a line.