summaryrefslogtreecommitdiffstats
path: root/_archive/arduino-due.md
diff options
context:
space:
mode:
Diffstat (limited to '_archive/arduino-due.md')
-rw-r--r--_archive/arduino-due.md112
1 files changed, 112 insertions, 0 deletions
diff --git a/_archive/arduino-due.md b/_archive/arduino-due.md
new file mode 100644
index 0000000..0551376
--- /dev/null
+++ b/_archive/arduino-due.md
@@ -0,0 +1,112 @@
+---
+title: Bare-metal ARM Cortex M3 chips
+date: 2024-10-05
+author: W. D. Sadeep Madurange
+layout: post
+---
+
+This post is about programming bare metal SAM3X8E Arm Cortex M3 chips found on
+Arduino Due boards. I had to learn how to do this because none of the
+high-level tools for programming Arduino Dues are available for OpenBSD, which
+I use for much of my personal computing.
+
+## Toolchain
+
+Since we will not be using pre-packaged development tools, we need to assemble
+our own toolchain. As usual, we need a compiler toolchain to build programs for
+the target chip. As we will be bypassing the embedded bootloader, we will also
+need a hardware programmer and an on-chip debugger to flash programs to the
+chip. I used the following toolchain.
+
+- <a href="https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain"
+ class="external" target="_blank" rel="noopener noreferrer">Arm GNU compiler
+ toolchain</a>.
+- <a href="https://openocd.org/" class="external" target="_blank"
+ rel="noopener noreferrer">OpenOCD</a> on-chip debugger.
+- <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.
+
+## Electrical connections
+
+The following diagram outlines the electrical connections between the different
+components necessary to move 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 SAM3X8E's Serial Wire Debug (SWD) interface via its
+DEBUG port. The ST-LINK/v2 programmer uses the SWD protocol to communicate with
+the chip.
+
+## Uploading the program
+
+Follow the steps below to upload a program to the SAM3X8E chip. The
+source.tar.gz tarball at the end of the page contains a sample program with a
+OpenOCD config file and a linker script.
+
+ 1. Start OpenOCD:
+ ```
+ $ openocd -f openocd-due.cfg
+ ```
+ 2. Open a telnet session and check that the GPNVM1 bit is set. Otherwise
+ set it to 1:
+
+ ```
+ $ telnet localhost 4444
+ > halt
+ > at91sam3 gpnvm show
+ > at91sam3 gpnvm set 1
+ > at91sam3 gpnvm show
+ ```
+ 3. Build the program using the custom linker script.
+ ```
+ $ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
+ -nostartfiles \
+ -nostdlib \
+ -o a.elf main.c
+ ```
+ 4. Upload the program using OpenOCD:
+ ```
+ $ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
+ ```
+
+Refer to the OpenOCD manual (AT91SAM3 flash driver section) for a complete list
+of commands supported for the ATSAM3X8E.
+
+## GPNVM bits and the linker script
+
+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
+(default), the chip boots from the ROM, which contains Atmel's SAM-BA
+bootloader. So, the chip runs the embedded bootloader instead of our program.
+
+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 using the linker script, we set the GPNVM1 bit and
+leave the GPNVM2 bit as it is.
+
+The linker script places the vector table at the first address of the flash.
+ARM chips expect this unless we relocate the vector table using the VTOR
+register. The first entry of the vector table must be the stack pointer, and
+the second must be the reset vector.
+
+Finally, the ATSAM3X8E uses a descending stack. So, in the linker script, we
+initialize the stack pointer to the highest memory location available. In the
+reset vector, we zero out memory, initialize registers, and perform other tasks
+before passing control to the main program.
+
+Files: [source.tar.gz](source.tar.gz)