1
2022-12-18 17:12:33 +00:00

224 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/jpg" href="https:&#x2F;&#x2F;branding.ewpratten.com&#x2F;pfp&#x2F;2022&#x2F;460x460.webp" />
<link rel="canonical" href="https:&#x2F;&#x2F;ewpratten.com&#x2F;blog&#x2F;32u4-upload&#x2F;" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="https://ewpratten.com/rss.xml">
<meta name="twitter:card" content="summary" />
<meta name="og:site" content="ewpratten.com" />
<meta name="og:site_name" content="Evan Pratten" />
<meta name="og:image"
content="https:&#x2F;&#x2F;branding.ewpratten.com&#x2F;pfp&#x2F;2022&#x2F;460x460.webp" />
<meta property="og:description" content="Notes for my future self" />
<meta property="description" content="Notes for my future self" />
<meta name="description" content="Notes for my future self">
<meta property="og:title" content="Flashing code to a 32u4 chip - Evan Pratten" />
<meta property="og:type" content="article" />
<title>Flashing code to a 32u4 chip | Evan Pratten</title>
<link rel="stylesheet" href="/global.css">
<link rel="stylesheet" href="/dist/github-markdown-css/github-markdown-light.css" lazyload>
<link rel="stylesheet" href="/styles/bootstrap.css" lazyload>
<link rel="stylesheet" href="/styles/typography.css">
</head>
<body>
<div class="page">
<link rel="stylesheet" href="/styles/components/heading-card.css">
<div class="heading-card">
<div class="profile-photo-container">
<img src="https:&#x2F;&#x2F;branding.ewpratten.com&#x2F;pfp&#x2F;2022&#x2F;460x460.webp" alt="Profile Photo" loading="lazy">
</div>
<div class="text-container">
<h1>Evan Pratten</h1>
<p>Software Developer</p>
</div>
</div>
<div class="container">
<link rel="stylesheet" href="/styles/components/navbar.css">
<div class="ewp-navbar">
<hr>
<ul class="navbar-items">
<li><a href="/">Home</a></li>
<li class="separator">|</li>
<li><a href="/timeline">Timeline</a></li>
<li class="separator">|</li>
<li class="dropdown-center">
<a href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
More
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/photography">Photography</a></li>
<li><a class="dropdown-item" href="/contact">Contact</a></li>
</ul>
</li>
</ul>
<hr>
</div>
</div>
<article id="content" class="container markdown-body">
<h1 style="margin-bottom:0;padding-bottom:0;">Flashing code to a 32u4 chip</h1>
<em>Notes for my future self</em>
<br><br>
<p>The <a rel="noopener" target="_blank" href="http://ww1.microchip.com/downloads/en/devicedoc/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf">ATmega32u4</a> (aka. 32u4) chip is one of my favorite microcontrollers to work with. It is a low power, 8-bit, <a rel="noopener" target="_blank" href="https://en.wikipedia.org/wiki/AVR_microcontrollers">AVR</a>-based system developed by <a rel="noopener" target="_blank" href="https://en.wikipedia.org/wiki/Atmel">Atmel</a>. They are commonly used in <a rel="noopener" target="_blank" href="https://www.arduino.cc/en/Main/Arduino_BoardLeonardo">Arduino Leonardo</a> development boards and programmed via the <a rel="noopener" target="_blank" href="https://www.arduino.cc/en/Main/Software">Arduino IDE</a>, but I prefer having as much control over the device as I can. So I choose to program these chips directly in <a rel="noopener" target="_blank" href="http://ww1.microchip.com/downloads/en/devicedoc/40001917a.pdf">AVRASM</a> and <a rel="noopener" target="_blank" href="https://www.nongnu.org/avr-libc/user-manual/">AVR-C</a>.</p>
<p>This post will go over how to easily flash code to a 32u4 chip from a Linux host, and exists as reference for when I inevitably need to refresh my memory in the future.</p>
<h2 id="getting-the-needed-tools">Getting the needed tools</h2>
<p>Before starting, the following tools are needed:</p>
<ul>
<li><a rel="noopener" target="_blank" href="https://github.com/vancegroup-mirrors/avr-libc/releases">AVR-libc</a></li>
<li><a rel="noopener" target="_blank" href="https://www.nongnu.org/avrdude/">avrdude</a></li>
</ul>
<h2 id="writing-a-hello-world-for-avr">Writing a &quot;Hello, world!&quot; for AVR</h2>
<p>Since you can't exactly &quot;print to console&quot; with a microprocessor, this &quot;Hello, world!&quot; will consist of toggling one of the 32u4's I/O pins once every half second. In this case, we will write to <code>PB5</code> (pin <code>9</code> on an Arduino Leonardo). If you don't understand how AVR code works, I recommend reading a simple tutorial. This program simply configures <code>DDRB</code> to allow output for <code>PB5</code>, and toggles the <code>PB5</code> bit in <code>PORTB</code> every 500ms.</p>
<pre data-lang="cpp" style="background-color:#2b303b;color:#c0c5ce;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="color:#65737e;">// main.cc
</span><span>
</span><span style="color:#b48ead;">#include </span><span>&lt;</span><span style="color:#a3be8c;">avr/io.h</span><span>&gt;
</span><span style="color:#b48ead;">#include </span><span>&lt;</span><span style="color:#a3be8c;">util/delay.h</span><span>&gt;
</span><span>
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span>(</span><span style="color:#b48ead;">int </span><span style="color:#bf616a;">argc</span><span>, </span><span style="color:#b48ead;">char const</span><span>* </span><span style="color:#bf616a;">argv</span><span>[]) {
</span><span>
</span><span> DDRB |= (</span><span style="color:#d08770;">1 </span><span>&lt;&lt; PB5);
</span><span> </span><span style="color:#b48ead;">for </span><span>(;;) {
</span><span> PORTB= </span><span style="color:#d08770;">0b00100000</span><span>;
</span><span> </span><span style="color:#bf616a;">_delay_ms</span><span>(</span><span style="color:#d08770;">500</span><span>);
</span><span> PORTB= </span><span style="color:#d08770;">0b00000000</span><span>;
</span><span> </span><span style="color:#bf616a;">_delay_ms</span><span>(</span><span style="color:#d08770;">500</span><span>);
</span><span> }
</span><span>
</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">0</span><span>;
</span><span>}
</span></code></pre>
<h2 id="compiling">Compiling</h2>
<p>This code can now be compiled with:</p>
<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">avr-g++ -DF_CPU</span><span>=16000000</span><span style="color:#bf616a;"> -D</span><span> __AVR_ATmega32U4__</span><span style="color:#bf616a;"> -mmcu</span><span>=atmega32u4</span><span style="color:#bf616a;"> -Iinclude -DBAUD</span><span>=9600</span><span style="color:#bf616a;"> -std</span><span>=c++11</span><span style="color:#bf616a;"> -g -Os -w -fdata-sections -MMD -flto -c -o</span><span> main.o main.cc
</span></code></pre>
<p>And linked with:</p>
<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">avr-g++ -w -Os -g -flto -fuse-linker-plugin -Wl</span><span>,--gc-sections</span><span style="color:#bf616a;"> -mmcu</span><span>=atmega32u4</span><span style="color:#bf616a;"> -Iinclude -std</span><span>=c++11</span><span style="color:#bf616a;"> -DF_CPU</span><span>=16000000</span><span style="color:#bf616a;"> -o</span><span> main.elf main.o
</span><span style="color:#bf616a;">avr-objcopy -O</span><span> ihex</span><span style="color:#bf616a;"> -j</span><span> .eeprom</span><span style="color:#bf616a;"> --set-section-flags</span><span>=.eeprom=alloc,load</span><span style="color:#bf616a;"> --no-change-warnings --change-section-lma</span><span> .eeprom=0 main.elf main.eep
</span><span style="color:#bf616a;">avr-objcopy -O</span><span> ihex</span><span style="color:#bf616a;"> -R</span><span> .eeprom main.elf main.hex
</span></code></pre>
<p>To create a HEX file for the program binary, and an eeprom dump. These are both going to be uploaded to the chip in the next step.</p>
<h2 id="flashing-the-32u4">Flashing the 32u4</h2>
<p>The 32u4 chip must be in it's bootloader in order to have it's memory written. This can be done in one of two ways. The first (my preference) is to quickly reset the chip before running avrdude by pulling the <code>RST</code> line to ground. You can also put the chip in it's bootloader by connecting to UART at <code>1200bps</code>. Once in the bootloader, the chip will stay there for 10 seconds.</p>
<p>WIth the 32u4 in it's bootloader, we can flash our compiled code with:</p>
<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">sudo</span><span> avrdude</span><span style="color:#bf616a;"> -patmega32u4 -cavr109 -P</span><span> /dev/ttyACM0</span><span style="color:#bf616a;"> -b57600 -v -U</span><span> flash:w:main.hex:i</span><span style="color:#bf616a;"> -U</span><span> eeprom:w:main.eep
</span></code></pre>
<p><em>NOTE: <code>/dev/ttyACM0</code> may need to be changed depending on the system</em></p>
<p>Once the code has uploaded, reset the chip to start the code.</p>
</article>
<link rel="stylesheet" href="/styles/components/footer.css">
<div class="footer">
<br>
<span class="gray">-- EOF --</span>
<p>
Site design & content by: <a href="/contact">Evan Pratten</a><br>
Consider <a href="/donate" target="_blank">supporting my work</a> if you like what you see<br>
</p>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script defer src="https://www.googletagmanager.com/gtag/js?id=G-5912H4H03P"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-5912H4H03P');
</script>
</body>
</html>