diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2025-11-07 21:07:12 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2025-11-09 08:32:51 +0800 |
| commit | 25615d16f93ffafcb19d0940cfab75e1f374b3b9 (patch) | |
| tree | 44c015e631cbd0fbeb5ccb6e821874ec4d299d02 /_archive/arduino-due.md | |
| parent | 1b4674f15331982ac83dbfa646985f62dc3f2e33 (diff) | |
| download | www-25615d16f93ffafcb19d0940cfab75e1f374b3b9.tar.gz | |
Improve writing.
Diffstat (limited to '_archive/arduino-due.md')
| -rw-r--r-- | _archive/arduino-due.md | 165 |
1 files changed, 89 insertions, 76 deletions
diff --git a/_archive/arduino-due.md b/_archive/arduino-due.md index 648bb4b..1b1f5ef 100644 --- a/_archive/arduino-due.md +++ b/_archive/arduino-due.md @@ -1,36 +1,44 @@ --- -title: Bare-metal ARM Cortex M3 chips +title: Bare-metal ATSAM3X8E chips date: 2024-10-05 author: Wickramage Don 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. +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. ## 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. +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. ## 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. +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. <table style="border: none; width: 100%;"> <tr style="border: none;"> @@ -45,66 +53,71 @@ components necessary to move a compiled program from a PC to the MCU. </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. +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 -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 set the GPNVM1 bit 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 +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: + +``` +$ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \ + -nostartfiles \ + -nostdlib \ + -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: + +``` +$ openocd -f openocd-due.cfg +$ telnet localhost 4444 + > halt + > at91sam3 gpnvm show + > at91sam3 gpnvm set 1 + > at91sam3 gpnvm show +$ 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. + +## 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 -(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. +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. + +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 + +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. + +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. + +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. Files: [source.tar.gz](source.tar.gz) |
