summaryrefslogtreecommitdiffstats
path: root/_log/arduino-due.md
diff options
context:
space:
mode:
Diffstat (limited to '_log/arduino-due.md')
-rw-r--r--_log/arduino-due.md103
1 files changed, 38 insertions, 65 deletions
diff --git a/_log/arduino-due.md b/_log/arduino-due.md
index 2cbd2f4..0d4f495 100644
--- a/_log/arduino-due.md
+++ b/_log/arduino-due.md
@@ -1,43 +1,27 @@
---
-title: How to set up ATSAM3X8E microcontrollers for bare-metal programming in C
+title: ATSAM3X8E bare-metal programming
date: 2024-09-16
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.
+Notes on programming ATSAM3X8E chips (Arduino Due) without bootloader. Tested
+on OpenBSD.
## 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.
+Need to bypass embedded bootloader—requires hardware programmer that speaks
+Serial Wire Debug (SWD). ST-LINK/V2 works as SWD-USB adapter.
+
+OpenOCD translates commands to binary sequences the chip understands. Runs
+telnet server on startup for issuing commands.
+
+ARM GNU Compiler Toolchain for compiling C programs. Both OpenOCD and ARM
+toolchain available on 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.
+Arduino Due exposes ATSAM3X8E's SWD interface via DEBUG port. ST-LINK/V2
+connects there.
<table style="border: none; width: 100%;">
<tr style="border: none;">
@@ -55,11 +39,10 @@ from a PC to the MCU.
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
+## Upload procedure
-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:
+Sample LED blink program with OpenOCD config and linker scripts in tarball
+below.
```
$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
@@ -68,8 +51,7 @@ $ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
-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:
+Upload:
```
$ openocd -f openocd-due.cfg
@@ -81,42 +63,33 @@ $ telnet localhost 4444
$ 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.
+First command starts OpenOCD. Telnet session halts chip, checks GPNVM bit. If
+unset (returns 0), set to 1 and verify. Final command uploads program. See
+OpenOCD manual AT91SAM3 flash driver section for full command list.
## 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.
+ARM chips boot into address 0x00000. ATSAM3X8E has ROM and dual-banked flash
+(flash0/flash1) at different addresses. GPNVM bits control which maps to
+0x00000.
+
+GPNVM1 cleared (default): boots from ROM (Atmel SAM-BA bootloader). GPNVM1=1,
+GPNVM2=0: flash0 (0x80000) maps to 0x00000. Both cleared: flash1 maps to
+0x00000.
+
+Program goes in flash0, so set GPNVM1=1 to boot our code instead of 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 notes
-## Linker script
+Vector table must be at first flash address--mandatory for ARM chips unless
+using VTOR register for relocation.
-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.
+First vector table entry: stack pointer. Initialize to highest memory location
+(ATSAM3X8E has descending stack).
-The first entry of the vector table must be the stack pointer. The stack
-pointer must be initialized to the highest memory location available to
-accommodate the ATSAM3X8E's descending stack.
+Second entry: reset vector. Place initialization code here (zero memory, set
+registers) before jumping to main().
-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.
+Commit:
+[3184969](https://git.asciimx.com/bare-metal-arduino-due/commit/?id=318496925ca76668dd9d63c3d060376f489276f8)
-Files: [source.tar.gz](source.tar.gz)