One of my EE co-workers got hold of an Arduino Zero recently but failed to get it working. I took a looks at this and realized that he had walked into the battle of the arduinos and was trying to use the wrong software. Currently Arduino.cc have not released the Zero but Arduino.org have released an Arduino Zero Pro and this is what we have here. To support this they have issued a version of the Arduino IDE labelled as 1.7.2 but which is really a 1.5ish version with Zero support bolted in. Quite poorly as well from a first look.

So having got the device and an IDE capable of programming it, we can try the basic serial output test as shown below. However, it turns out that the included examples will not work as the default Serial class is the wrong one. To get this working Serial5 needs to be used.

#include <Arduino.h>

// for the Arduino Zero
#ifdef __SAMD21G18A__
#define Serial Serial5
#endif

static int n = 0x10;

void setup()
{
    Serial.begin(115200);
    Serial.println("Serial test - v1.0.0");
}

void loop()
{
    Serial.print(n++, HEX);
    if (n % 0x10 == 0)
        Serial.println("");
    else
        Serial.print(" ");
    if (n > 0xff)
        n = 0x10;
    delay(30);
}

Moving on I thought it would be interesting to try and use this with a WizNet based Ethernet shield I have. So with the board set as Arduino Zero let us build one of the Ethernet demos.

C:\opt\arduino.org-1.7.2\libraries\Ethernet\src\Ethernet.cpp: In member function 'int EthernetClass::begin(uint8_t*)':
C:\opt\arduino.org-1.7.2\libraries\Ethernet\src\Ethernet.cpp:19:7: error: 'class SPIClass' has no member named 'beginTransaction'
   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);

I sincerely hope arduino.cc do a better job than this when they release their version of this interesting board.

Debugging on the Zero

The ability to use gdb to debug the firmware is what makes this board so attractive. The 1.7.2 IDE package includes a copy of OpenOCD with configuration files for communicating with the Zero. While this is not integrated into the current IDE at all it is still possble to start stepping through the firmware. You do need to know something about the way the Arduino IDE handles building files to make use of this however.

OpenOCD is run as a server that mediates communications with the hardware. The following script makes it simple to launch OpenOCD in a separate window on Windows (adjust the Arduino directory path as appropriate). This gives a console showing any OpenOCD output and two TCP/IP ports will be opened. One on 4444 is for communicating with OpenOCD itself. The other on 3333 is for debugging.

@setlocal
@set ARDUINO_DIR=C:\opt\arduino.org-1.7.2
@set OPENOCD_DIR=%ARDUINO_DIR%\hardware\tools\OpenOCD-0.9.0-dev-arduino
@start "OpenOCD" %OPENOCD_DIR%\bin\openocd ^
  --file %ARDUINO_DIR%\hardware\arduino\samd\variants\arduino_zero\openocd_scripts\arduino_zero.cfg ^
  --search %OPENOCD_DIR%\share\openocd\scripts %*

To connect for debugging it is necessary to run a suitable version of gdb and set it to use the remote target provided by OpenOCD on localhost:3333. Provided the sources (the arduino .ino file and any .cpp or .h files included with the project) and the .elf binary are specified gdb can start showing symbolic debugging information. This is where the Arduino IDE needs to provide some assistance. The .ino source file is processed to produce some C++ files and then built with g++ but this all happens in a temporary directory with some relatively random name. Looking for the most recent directory in your temporary directory (%TEMP%) will have the build files. From this folder, running arm-none-eabi-gdb.exe and running the following commands in gdb will enable symbols and start controlling the firmware. After that it is normal gdb debugging.

Note that gdb is found at <ARDUINODIR>\hardware\tools\gcc-arm-none-eabi-4.8.3-2014q1\bin\arm-none-eabi-gdb.exe

# gdb commands...
directory SKETCHFOLDER\\PROJECTNAME
file PROJECTNAME.cpp.elf
target remote localhost:3333
monitor reset halt
break setup
continue

Worked example

Launching OpenOCD using the script described above.

Open On-Chip Debugger 0.9.0-dev-g1deebff (2015-02-19-15:29)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'cmsis-dap'
adapter speed: 500 kHz
adapter_nsrst_delay: 100
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.1F.0118
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : DAP_SWJ Sequence (reset: 50+ '1' followed by 0)
Info : CMSIS-DAP: Interface ready
Info : clock speed 500 kHz
Info : IDCODE 0x0bc11477
Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints

Launching gdb

GNU gdb (GNU Tools for ARM Embedded Processors) 7.6.0.20140228-cvs
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file SerialTest1.cpp.elf
Reading symbols from C:\Users\pt111992\AppData\Local\Temp\build1861788453707041664.tmp\SerialTest1.cpp.elf...done.
(gdb) directory c:\\src\\Arduino\\SerialTest1
Source directories searched: c:\src\Arduino\SerialTest1;$cdir;$cwd
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x000028b8 in ?? ()
(gdb) monitor reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x000028b8 msp: 0x20002c08
(gdb) break setup
Breakpoint 1 at 0x415e: file SerialTest1.ino, line 12.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, setup () at SerialTest1.ino:12
12          Serial.begin(115200);
(gdb) next
setup () at SerialTest1.ino:13
13          Serial.println("Serial test - v1.0.0");
(gdb)

And now we are stepping through the code actually running on the Arduino Zero. Awesome!