summaryrefslogtreecommitdiffstats
path: root/_site/archive/arduino-due
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2025-11-07 21:07:12 +0800
committerSadeep Madurange <sadeep@asciimx.com>2025-11-09 08:32:51 +0800
commit25615d16f93ffafcb19d0940cfab75e1f374b3b9 (patch)
tree44c015e631cbd0fbeb5ccb6e821874ec4d299d02 /_site/archive/arduino-due
parent1b4674f15331982ac83dbfa646985f62dc3f2e33 (diff)
downloadwww-25615d16f93ffafcb19d0940cfab75e1f374b3b9.tar.gz
Improve writing.
Diffstat (limited to '_site/archive/arduino-due')
-rw-r--r--_site/archive/arduino-due/index.html149
1 files changed, 77 insertions, 72 deletions
diff --git a/_site/archive/arduino-due/index.html b/_site/archive/arduino-due/index.html
index 13e006e..86f4fb0 100644
--- a/_site/archive/arduino-due/index.html
+++ b/_site/archive/arduino-due/index.html
@@ -2,12 +2,12 @@
<html>
<head>
<meta charset="utf-8">
- <title>Bare-metal ARM Cortex M3 chips</title>
+ <title>Bare-metal ATSAM3X8E chips</title>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Bare-metal ARM Cortex M3 chips</title>
+ <title>Bare-metal ATSAM3X8E chips</title>
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/skeleton.css">
</head>
@@ -40,34 +40,38 @@
<main>
<div class="container">
- <h2 class="center" id="title">BARE-METAL ARM CORTEX M3 CHIPS</h2>
+ <h2 class="center" id="title">BARE-METAL ATSAM3X8E CHIPS</h2>
<h6 class="center">05 OCTOBER 2024</h5>
<br>
- <div class="twocol justify"><p>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.</p>
+ <div class="twocol justify"><p>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.</p>
<h2 id="toolchain">Toolchain</h2>
-<p>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.</p>
+<p>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.</p>
-<ul>
- <li><a href="https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain" class="external" target="_blank" rel="noopener noreferrer">Arm GNU compiler
-toolchain</a>.</li>
- <li><a href="https://openocd.org/" class="external" target="_blank" rel="noopener noreferrer">OpenOCD</a> on-chip debugger.</li>
- <li><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.</li>
-</ul>
+<p>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.</p>
+
+<p>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.</p>
<h2 id="electrical-connections">Electrical connections</h2>
-<p>The following diagram outlines the electrical connections between the different
-components necessary to move a compiled program from a PC to the MCU.</p>
+<p>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.</p>
<table style="border: none; width: 100%;">
<tr style="border: none;">
@@ -82,69 +86,70 @@ components necessary to move a compiled program from a PC to the MCU.</p>
</tr>
</table>
-<p>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.</p>
+<p>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.</p>
<h2 id="uploading-the-program">Uploading the program</h2>
-<p>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.</p>
-
-<ol>
- <li>Start OpenOCD:
- <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ openocd -f openocd-due.cfg
-</code></pre></div> </div>
- </li>
- <li>Open a telnet session and set the GPNVM1 bit to 1:
- <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 4444
+<p>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:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
+ -nostartfiles \
+ -nostdlib \
+ -o a.elf main.c
+</code></pre></div></div>
+
+<p>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:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ openocd -f openocd-due.cfg
+$ telnet localhost 4444
&gt; halt
&gt; at91sam3 gpnvm show
&gt; at91sam3 gpnvm set 1
&gt; at91sam3 gpnvm show
-</code></pre></div> </div>
- </li>
- <li>Build the program using the custom linker script.
- <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
- -nostartfiles \
- -nostdlib \
- -o a.elf main.c
-</code></pre></div> </div>
- </li>
- <li>Upload the program using OpenOCD:
- <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
-</code></pre></div> </div>
- </li>
-</ol>
+$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
+</code></pre></div></div>
-<p>Refer to the OpenOCD manual (AT91SAM3 flash driver section) for a complete list
-of commands supported for the ATSAM3X8E.</p>
+<p>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.</p>
-<h2 id="gpnvm-bits-and-the-linker-script">GPNVM bits and the linker script</h2>
+<p>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.</p>
+
+<h2 id="gpnvm-bits">GPNVM bits</h2>
<p>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.</p>
-
-<p>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.</p>
-
-<p>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.</p>
-
-<p>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.</p>
-
-<p>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.</p>
+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.</p>
+
+<p>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.</p>
+
+<h2 id="linker-script">Linker script</h2>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>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.</p>
<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>
</div>