Getting your compiled code into a custom System on Chip (SoC) with a Cortex M0 processor through the Serial Wire Debug (SWD) interface involves a few key steps. First, you need to compile your code into a binary file format that the processor can understand. Then, you need to connect to the SWD interface on your SoC to load the binary file into the flash memory on the chip. Finally, you need to configure the processor to boot from flash so it will run your new code on start up.
Compiling Code for Cortex M0
The first step is to compile your C/C++ code into an executable binary file. Most Cortex M0 chips use the Arm Thumb instruction set, so you need to compile for this architecture. The most common output format is an ELF (Executable and Linkable Format) file. This contains your compiled machine code along with metadata like symbols. The compiler will also generate a HEX or BIN file which contains just the executable machine code.
For example, with GCC you would compile your code with flags like: gcc -mcpu=cortex-m0 -mthumb -o code.elf code.c
The -mcpu flag targets the Cortex M0 architecture specifically. The -mthumb flag means to use the Thumb instruction set. This will generate code.elf which contains the compiled machine code.
To get just the binary, use objcopy: objcopy -O binary code.elf code.bin
This strips out the metadata and gives you code.bin which is the raw machine code that can be loaded onto the chip.
Connecting to SWD Interface
SWD stands for Serial Wire Debug. This is a debug interface built into most Cortex M chips including the M0. It provides a connection over which you can load code, inspect registers, set breakpoints, and debug your program.
To connect to SWD, you need an SWD adapter. Many development boards come with an onboard SWD interface. For a custom board, you may need an external adapter like a J-Link or ST-Link. There are also many low cost SWD adapters available.
Connect the SWD adapter to the SWD pins on your board. This usually includes the SWD clock (SWCLK), SWD data (SWDIO), ground, and power pins. Make sure your adapter and SoC are powered on.
Loading Code over SWD
With the SWD hardware connected, you can now load code into the flash memory on your chip. Most SWD adapters come with compatible software to interface with the debug connection.
For example, with a J-Link SWD adapter you would use J-Link Commander software. To load a BIN file over SWD, you can use the loadbin command: J-Link> loadbin code.bin, 0x0
This will load code.bin into the flash starting at address 0x0. The software will connect to the SWD interface and stream the binary down to program the flash.
Similar commands are available in STM32CubeProgrammer, OpenOCD, and other SWD interface software. The key things to specify are the binary file and the flash address to program.
Configuring the Reset Vector
After flashing your new code, you need to configure the processor to boot from that flash. On Cortex M cores, the boot sequence starts by loading the stack pointer and program counter from a fixed reset vector address on start up.
By default, this reset vector points to internal flash. To boot your new code, you need to reprogram this vector. For a Cortex M0, the reset vector is located at address 0x0 in the flash.
When you loaded your binary over SWD, it should have programmed address 0x0 with a branch instruction to the start of your code. Now on reset, it will load this address, branch to your code, and begin executing it.
To be safe, you can double check the value at address 0x0 matches the entry point of your binary. You can view memory through the SWD debug interface. This confirms the reset sequence will work properly.
Debugging with SWD
A major benefit of SWD is the ability to debug code running on the chip. By connecting to SWD, you can set breakpoints, inspect registers and memory, watch variables, and step through code.
For example, to debug a crash, you can set a breakpoint near the crash location. The processor will halt when it hits this breakpoint over SWD. You can then inspect the call stack and local variables to see what went wrong.
SWD debugging requires integrated debug hardware on the SoC. Most Cortex M chips include an Embedded Trace Macrocell (ETM) or Micro Trace Buffer (MTB) for full debug support over SWD.
Debugging also requires debug symbols from your compiled ELF file. The debugger maps machine code addresses back to your C source code using this symbol table.
Combined with the capabilities of SWD, on-chip debug hardware enables powerful debugging and troubleshooting during development.
The SWD interface also enables remote debugging. Rather than needing physical access to a debug connector, you can use remote SWD adapters.
Solutions like SEGGER Ozone provide J-Link support across Ethernet networks. The J-Link connects locally to the SWD port, then tunnels the connection over a LAN or WAN to your computer.
There are also many inexpensive SWD adapters for mobile devices like ST-Link MOBI, which provides SWD from an Android device. This lets you debug directly from your phone or tablet.
These remote options enable debugging products in the field or manufacturing lines far away from your desktop. You also gain the flexibility to debug from multiple devices by tunneling SWD.
While extremely useful for development, SWD also introduces security risks for production devices. The direct memory access allows circumventing flash encryption or DRM.
Options like one-time programmable SWD fuses can lock the interface after development use. The interface can also be locked by flash-programming password registers.
For ultimate security, SWD pins can be disconnected by altering the PCB routing. This physically disables the interface without internal access.
Balancing development utility and production security requires thoughtful design. But disabling SWD when no longer needed is highly recommended for any production SoC.
Getting code into a custom SoC using the Cortex M0 and SWD interface requires compiling your code for the Thumb instruction set, connecting to the chip’s SWD pins with an adapter, loading the binary into flash memory over SWD, configuring the reset vector, and optionally using SWD for debugging.
Following these steps allows loading arbitrary programs onto the device. With integrated debug features, SWD provides invaluable development access and visibility into the processor and memory system.
SWD is a key enabler for rapid prototyping on custom hardware. But it also introduces security risks that must be mitigated for any final production system.