ATSAM3X8E BARE-METAL NOTES
16 SEPTEMBER 2024
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.
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.
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:
Wiring |
Arduino Due |
Remap memory using OpenOCD:
$ openocd -f openocd-due.cfg
$ telnet localhost 4444
> halt
> at91sam3 gpnvm show
> at91sam3 gpnvm set 1
> at91sam3 gpnvm show
Full command list in OpenOCD manual AT91SAM3 (flash driver section).
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 \
-nostartfiles \
-nostdlib \
-o a.elf main.c
$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
Chip unlocked. I’m in.
Commit: 3184969.