summaryrefslogtreecommitdiffstats
path: root/_blog/arduino-due.md
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2025-12-08 17:34:35 +0800
committerSadeep Madurange <sadeep@asciimx.com>2025-12-08 21:05:19 +0800
commit752a06ec0ebf20d6232b13f1ea53fe21fefcefbd (patch)
tree690411afad8eb76216417a42de94135214cb2401 /_blog/arduino-due.md
parent20b0a045a7dc78f9728837fe5a1be8cf12caae4e (diff)
downloadwww-752a06ec0ebf20d6232b13f1ea53fe21fefcefbd.tar.gz
Fix list indentation.
Diffstat (limited to '_blog/arduino-due.md')
-rw-r--r--_blog/arduino-due.md122
1 files changed, 122 insertions, 0 deletions
diff --git a/_blog/arduino-due.md b/_blog/arduino-due.md
new file mode 100644
index 0000000..7c0fb12
--- /dev/null
+++ b/_blog/arduino-due.md
@@ -0,0 +1,122 @@
+---
+title: How to set up ATSAM3X8E microcontrollers for bare-metal programming in C
+date: 2024-10-05
+layout: post
+---
+
+This article is a step-by-step guide for programming bare-metal ATSAM3X8E chips
+found on Arduino Due boards. It also includes notes on the chip's memory layout
+relevant for writing linker scripts. The steps described in this article were
+tested on an OpenBSD workstation.
+
+## Toolchain
+
+To interact directly with a bare-metal ATSAM3X8E chips, we must bypass the
+embedded bootloader. To do that, we need a hardware programmer capable of
+communicating with the chip over the Serial Wire Debug (SWD) protocol. Since
+the workstation we upload the program from presumably doesn't speak SWD, the
+hardware programmer acts as a SWD-USB adapter. The <a
+href="https://www.st.com/en/development-tools/st-link-v2.html" class="external"
+target="_blank" rel="noopener noreferrer">ST-LINK/V2</a> programmer fits this
+bill.
+
+The <a href="https://openocd.org/" class="external" target="_blank"
+rel="noopener noreferrer">OpenOCD</a> on-chip debugger software supports
+ATSAM3X8E chips. OpenOCD, on startup, runs a telnet server that we can connect to
+to issue commands to the ATSAM3X8E chip. OpenOCD translates plain-text commands
+into the binary sequences the chip understands, and sends them over the wire.
+
+Finally, we need the <a
+href="https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain"
+class="external" target="_blank" rel="noopener noreferrer">ARM GNU Compiler
+Toolchain</a> to compile C programs for the chip. The ARM GNU compiler
+toolchain and OpenOCD, as a consequence of being free software, are available
+on every conceivable platform, including OpenBSD.
+
+## Electrical connections
+
+The following photos illustrate the electrical connections between the Arduino
+Due, PC, and the ST-LINK/V2 programmer required to transfer a compiled program
+from a PC to the MCU.
+
+<table style="border: none; width: 100%;">
+ <tr style="border: none;">
+ <td style="border: none; width: 50%; vertical-align: top; background-color: transparent;">
+ <img src="schematic.png" alt="Pinout" style="width: 100%">
+ <p style="text-align: center;">Wiring</p>
+ </td>
+ <td style="border: none; width: 50%; vertical-align: top; background-color: transparent;">
+ <img src="connections.jpeg" alt="Circuit" style="width: 100%">
+ <p style="text-align: center;">Arduino Due</p>
+ </td>
+ </tr>
+</table>
+
+Arduino Due exposes the ATSAM3X8E's SWD interface via its DEBUG port. The
+ST-LINK/v2 programmer connects to that to communicate with the chip.
+
+## Uploading the program
+
+The source.tar.gz tarball at the end of this page contains a sample C program
+(the classic LED blink program) with OpenOCD configuration and linker scripts.
+First, use the following command to build it:
+
+```
+$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
+ -nostartfiles \
+ -nostdlib \
+ -o a.elf main.c
+```
+
+Then, open a telnet session with OpenOCD and issue the following sequence of
+commands to configure the chip and upload the compiled program to it:
+
+```
+$ openocd -f openocd-due.cfg
+$ telnet localhost 4444
+ > halt
+ > at91sam3 gpnvm show
+ > at91sam3 gpnvm set 1
+ > at91sam3 gpnvm show
+$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
+```
+
+The first of the above commands starts OpenOCD. In the telnet session, the
+first command halts the chip in preparation for receiving commands. Next, we
+inspect the current GPNVM bit setting (more on this later). If the bit is unset
+(the gpnvm show command returns 0), we set it to 1 and verify the update.
+
+The final command, issued from outside the telnet session, uploads the program
+to the chip. Those are the bare minimum set of commands required to program the
+chip. The AT91SAM3 flash driver section of the OpenOCD manual lists all
+available commands for the ATSAM3X8E chip.
+
+## GPNVM bits
+
+By design, ARM chips boot into address 0x00000. ATSAM3X8E's memory consists of
+a ROM and a dual-banked flash (flash0 and flash1), residing in different
+locations of the chip's address space. The GPNVM bits control which of them
+maps to 0x00000. When GPNVM1 is cleared (the default), the chip boots from the ROM,
+which contains Atmel's SAM-BA bootloader.
+
+Conversely, when the GPNVM1 bit is 1 (and the GPNVM2 bit is 0), flash0 at
+address 0x80000 maps to 0x00000. When both GPNVM bits are 0, flash1 maps to
+0x00000. Since we place our program in flash0 in the linker script, we set the
+GPNVM1 bit and leave the GPNVM2 bit unchanged to ensure the chip
+executes our program instead of the embedded bootloader at startup.
+
+## Linker script
+
+At a minimum, the linker script must place the vector table at the first
+address of the flash. This is mandatory for ARM chips unless we relocate the
+vector table using the VTOR register.
+
+The first entry of the vector table must be the stack pointer. The stack
+pointer must be initializes to the highest memory location available to
+accommodate the ATSAM3X8E's descending stack.
+
+The second entry of the vector table must be the reset vector. In the reset
+vector, we can perform tasks such as zeroing out memory and initializing
+registers before passing control to the main program.
+
+Files: [source.tar.gz](source.tar.gz)