summaryrefslogtreecommitdiffstats
path: root/_log
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2026-02-22 14:32:31 +0800
committerSadeep Madurange <sadeep@asciimx.com>2026-02-23 20:17:23 +0800
commit05e9ffff4362e31db761e268ae0735d2a1fd231a (patch)
treeb333822d5af5b9c0b5841abe18df881c1338b41d /_log
parent931c7a4f2422c1499bfabcc5d6063b40b9c1dabe (diff)
downloadwww-05e9ffff4362e31db761e268ae0735d2a1fd231a.tar.gz
Improve arduino due post to make it more journal-like.
Diffstat (limited to '_log')
-rw-r--r--_log/arduino-due.md75
1 files changed, 65 insertions, 10 deletions
diff --git a/_log/arduino-due.md b/_log/arduino-due.md
index 8176b3b..1881547 100644
--- a/_log/arduino-due.md
+++ b/_log/arduino-due.md
@@ -4,19 +4,22 @@ date: 2024-09-16
layout: post
---
-Bypassing ATSAM3X8E (Due) bootloader via Serial Wire Debug (SWD).
+Bought an Arduino Due to play with ARM Cortex chips. Locked out of the chip for
+days—no dev tools (Arduino IDE, Microchip Studio) for OpenBSD. Need to find a
+way to bring up the bare-metal ATSAM3X8E.
-Toolchain: ST-LINK/V2 programmer, OpenOCD, ARM GNU Compiler Toolchain.
-
-ARM chips boot into 0x00000. GPNVM bits map one of ROM, flash0, flash1 to
-0x00000:
+Three on-chip memories: ROM, flash0, flash1. ARM Cortex-M chips boot into
+0x00000. GPNVM bits map one of them to 0x00000:
- GPNVM1=0 → ROM (default).
- GPNVM1=1 and GPNVM2=0 → flash0.
- GPNVM1=1 and GPNVM2=1 → flash1.
-By default, control jumps to Atmel's SAM-BA bootloader in ROM. To bypass, set
-GPNVM1=1 and place vector table at 0x80000 (flash0).
+On power-up, control jumps to ROM. Without a user program, Atmel's SAM-BA
+bootloader traps execution in ROM. Must remap memory via SWD to force chip to
+boot from flash, bypassing factory bootloader.
+
+Toolchain: ST-LINK/V2 programmer, OpenOCD, ARM GNU Compiler Toolchain.
Connect ST-LINK/v2 to Arduino Due's DEBUG port:
@@ -33,7 +36,7 @@ Connect ST-LINK/v2 to Arduino Due's DEBUG port:
</tr>
</table>
-Remap memory:
+Remap memory using OpenOCD:
```
$ openocd -f openocd-due.cfg
@@ -44,9 +47,59 @@ $ telnet localhost 4444
> at91sam3 gpnvm show
```
-Full command list is in OpenOCD manual AT91SAM3 (flash driver section).
+Full command list in OpenOCD manual AT91SAM3 (flash driver section).
-Compile and upload program:
+At a minimum, vector table must be initialized with stack pointer and reset
+vector:
+
+```
+__attribute__((noreturn)) void _reset(void)
+{
+ unsigned long *dst, *src;
+ extern unsigned long _sbss, _ebss;
+ extern unsigned long _sdata, _edata, _sidata;
+
+ for (dst = &_sbss; dst < &_ebss; dst++)
+ *dst = 0;
+ for (dst = &_sdata, src = &_sidata; dst < &_edata;)
+ *dst++ = *src++;
+
+ main();
+}
+
+extern const unsigned int _sp;
+
+__attribute__ ((section(".vtor"))) const void* _tab[] = { &_sp, _reset };
+```
+
+Linker script places vector table at start of flash0 and initializes stack
+pointer to top of RAM (descending stack):
+
+```
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x00080000, LENGTH = 512K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
+}
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.vtor))
+ *(.text*)
+ *(.rodata*)
+ } > rom
+}
+
+_sp = ORIGIN(ram) + LENGTH(ram);
+```
+
+Getting linker script right wasn't easy—long hours with the datasheet, OpenOCD
+manual. David Barrass from OpenBSD and folks at OpenOCD mailing lists (bless
+them!) helped generously.
+
+Build and upload program:
```
$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
@@ -56,6 +109,8 @@ $ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
```
+Chip unlocked. I'm in.
+
Commit: <a
href="https://git.asciimx.com/bare-metal-arduino-due/commit/?id=318496925ca76668dd9d63c3d060376f489276f8"
class="external" target="_blank" rel="noopener noreferrer">3184969</a>.