1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title>
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/skeleton.css">
</head>
</head>
<body>
<div id="nav-container" class="container">
<ul id="navlist" class="left">
<li >
<a href="/" class="link-decor-none">hme</a>
</li>
<li class="active">
<a href="/archive/" class="link-decor-none">blg</a>
</li>
<li >
<a href="/projects/" class="link-decor-none">poc</a>
</li>
<li >
<a href="/about/" class="link-decor-none">abt</a>
</li>
<li><a href="/feed.xml" class="link-decor-none">rss</a></li>
</ul>
</div>
<main>
<div class="container">
<div class="container-2">
<h2 class="center" id="title">HOW TO SET UP ATSAM3X8E MICROCONTROLLERS FOR BARE-METAL PROGRAMMING IN C</h2>
<h6 class="center">05 OCTOBER 2024</h5>
<br>
<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>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>
<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 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;">
<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>
<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>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
> halt
> at91sam3 gpnvm show
> at91sam3 gpnvm set 1
> at91sam3 gpnvm show
$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
</code></pre></div></div>
<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>
<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. 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>
<p class="post-author right">by W. D. Sadeep Madurange</p>
</div>
</div>
</main>
<div class="footer">
<div class="container">
<div class="twelve columns right container-2">
<p id="footer-text">© ASCIIMX - 2025</p>
</div>
</div>
</div>
</body>
</html>
|