<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Christopher McClellan</title>
    <description>The latest articles on DEV Community by Christopher McClellan (@rubberduck).</description>
    <link>https://dev.to/rubberduck</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2789%2F2716800.png</url>
      <title>DEV Community: Christopher McClellan</title>
      <link>https://dev.to/rubberduck</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rubberduck"/>
    <language>en</language>
    <item>
      <title>Debugging Rust Cortex-M with VS Code: Take 2</title>
      <dc:creator>Christopher McClellan</dc:creator>
      <pubDate>Tue, 31 Dec 2019 15:23:14 +0000</pubDate>
      <link>https://dev.to/rubberduck/debugging-rust-cortex-m-with-vs-code-take-2-248j</link>
      <guid>https://dev.to/rubberduck/debugging-rust-cortex-m-with-vs-code-take-2-248j</guid>
      <description>&lt;p&gt;Last time, I wrote about &lt;a href="https://christopherjmcclellan.wordpress.com/2019/11/29/debugging-rust-arm-cortexm-programs-with-visual-studio-code/"&gt;how to configure VS Code to debug Rust Cortex-M programs&lt;/a&gt;, but you know what's better than writing documentation for how to do a thing?&lt;/p&gt;

&lt;p&gt;Automating it.&lt;/p&gt;

&lt;p&gt;I'm very happy to announce my PR to add a basic debug configuration for VS Code has been merged into the &lt;a href="https://github.com/rust-embedded/cortex-m-quickstart"&gt;cortex-m-quickstart template&lt;/a&gt;. VS Code is now supported out of the box when you &lt;code&gt;cargo generate&lt;/code&gt; a new project. When I say "out of the box", I really mean "out of the box". I've also added a QEMU configuration, so you can go experiment with debugging embedded Rust with VS Code right now, without any additional hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;First, ensure you've &lt;a href="https://rust-embedded.github.io/book/intro/install.html"&gt;installed Rust, the ARM Cortex-M toolchain,  QEMU, and OpenOCD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, ensure you've installed &lt;code&gt;cargo generate&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-generate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lastly, install the necessary VS Code plugins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; rust-lang.rust
&lt;span class="go"&gt;Installing extensions...
Installing extension 'rust-lang.rust' v0.7.0...
Extension 'rust-lang.rust' v0.7.0 was successfully installed.

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; marus25.cortex-debug
&lt;span class="go"&gt;Installing extensions...
Installing extension 'marus25.cortex-debug' v0.3.4...
Extension 'marus25.cortex-debug' v0.3.4 was successfully installed.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can generate a new project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cargo generate &lt;span class="nt"&gt;--git&lt;/span&gt; https://github.com/rust-embedded/cortex-m-quickstart &lt;span class="nt"&gt;--name&lt;/span&gt; cortexm-app
&lt;span class="go"&gt;🔧   Creating project called `cortexm-app`...
✨   Done! New project created /Users/rubberduck/src/cortexm-app
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's go ahead and open it in Code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;code cortexm-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging with QEMU
&lt;/h2&gt;

&lt;p&gt;It is recommended you complete the &lt;a href="https://rust-embedded.github.io/book/start/qemu.html"&gt;QEMU section of The Book&lt;/a&gt; before moving forward, although, it's probably not necessary.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;src/main.rs&lt;/code&gt; and set a breakpoint.
&lt;/li&gt;
&lt;li&gt;Go to the debug screen and run the &lt;code&gt;Debug (QEMU)&lt;/code&gt; configuration.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QBqCGItf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbt59du8ijdbausp1nk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QBqCGItf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbt59du8ijdbausp1nk0.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project will automatically be built targeting the &lt;code&gt;LM3S6965EVB&lt;/code&gt; MCU, the resulting executable used to start QEMU, and then break when execution hits the entry point. You can then step through the code as you will.&lt;/p&gt;

&lt;p&gt;If you prefer not to break on &lt;code&gt;main&lt;/code&gt;, set &lt;code&gt;runToMain&lt;/code&gt; to false in the &lt;code&gt;.vscode/launch.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"runToMain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's pretty much it. I told you it worked out of the box. Feel free to play with the examples that come with the &lt;code&gt;cortex-m-quickstart&lt;/code&gt; template. The easiest thing to do, at the moment, is to copy the code into &lt;code&gt;src/main.rs&lt;/code&gt; and run the &lt;code&gt;Debug (QEMU)&lt;/code&gt; task. This will ensure the code is built prior to starting the emulator. You could also build the executable from the command line and modify the &lt;code&gt;launch.json&lt;/code&gt; file to point to the example, if you wish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--example&lt;/span&gt; hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;

    &lt;span class="c1"&gt;// "executable": "./target/thumbv7m-none-eabi/debug/testapp",&lt;/span&gt;
    &lt;span class="cm"&gt;/* Run `cargo build --example hello` and uncomment this line to run semi-hosting example */&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./target/thumbv7m-none-eabi/debug/examples/hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Currently, the Rust Language Server extension doesn't directly support building an example, although we could create a new configuration and &lt;a href="https://code.visualstudio.com/docs/editor/tasks#_custom-tasks"&gt;shell build task&lt;/a&gt; that executes the right &lt;code&gt;cargo build&lt;/code&gt; command. &lt;br&gt;
I consider this to be an area for improvement in the future but, honestly, it's a good exercise for the reader. These default configurations aren't meant to be the "end all, be all". They're meant to be a starting point for you to create debug configurations that meet your and your project's needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Debugging on Hardware
&lt;/h2&gt;

&lt;p&gt;Like &lt;a href="https://christopherjmcclellan.wordpress.com/2019/11/29/debugging-rust-arm-cortexm-programs-with-visual-studio-code/"&gt;last time&lt;/a&gt;, we'll be using the &lt;a href="https://www.st.com/en/evaluation-tools/stm32f3discovery.html#"&gt;STM32F3DISCOVERY board&lt;/a&gt; as our hardware.&lt;/p&gt;

&lt;p&gt;Before you tackle this section, it is &lt;em&gt;highly&lt;/em&gt; recommend you &lt;a href="https://rust-embedded.github.io/book/start/hardware.html"&gt;work through doing this from the command line&lt;/a&gt; to ensure you've installed the tools and properly setup your project. Unlike the QEMU section, debugging on hardware requires we modify a few files. I've included a brief summary below, but I really do encourage you to work through &lt;a href="https://rust-embedded.github.io/book/start/hardware.html"&gt;this chapter of The Embedded Rust Book first&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;.cargo/config&lt;/code&gt;, ensure you've set your build target to &lt;code&gt;thumbv7em-none-eabihf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"thumbv7em-none-eabihf"&lt;/span&gt; &lt;span class="c"&gt;# Cortex-M4F and Cortex-M7F (with FPU)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then ensure you have the correct memory layout in the &lt;code&gt;memory.x&lt;/code&gt; linker script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Linker script for the STM32F303VCT6 */
MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With that out of the way, we can connect our hardware via USB to the ST-Link port and launch a debug session. This time we'll use the &lt;code&gt;Debug (OpenOCD)&lt;/code&gt; configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I_HHQr1r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hawbw6s671k3g0lx6kml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I_HHQr1r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hawbw6s671k3g0lx6kml.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll notice that "Cortex Peripherals" aren't loading. That's because, for licensing reasons, we couldn't include the &lt;code&gt;*.svd&lt;/code&gt; file in the quickstart template. If you go to &lt;a href="https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32f3-series.html#resource"&gt;ST's website for the STM32F3 series&lt;/a&gt;, you can find and download the SVD pack (or just &lt;a href="https://www.st.com/resource/en/svd/stm32f3_svd.zip"&gt;download the STM32F3 SVD pack from this link&lt;/a&gt;). Once you've unzipped the package, just copy the &lt;code&gt;STM32F303.svd&lt;/code&gt; file into the &lt;code&gt;.vscode/&lt;/code&gt; directory and start a new debug session. The quickstart is configured to look here for the SVD, so you should now see all of the peripherals loaded into the editor.&lt;/p&gt;

&lt;p&gt;Of course, you could keep this file anywhere you like and just modify this line of the &lt;code&gt;.vscode/launch.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"svdFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}/.vscode/STM32F303.svd"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Personally, I like keeping them in my home directory so I don't have to keep multiple copies of the SVD on disk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"svdFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${env:HOME}/.svd/en.stm32f3_svd/STM32F3_svd_V1.2/STM32F303.svd"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you're working on a shared project though, you may want to use the default location and check the file in. That way, everyone who clones your project has a working configuration as soon as they've cloned it.&lt;br&gt;
Which brings us to...&lt;/p&gt;
&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;By default, all files in the &lt;code&gt;.vscode/&lt;/code&gt; directory are ignored by Git. There are a number of files that can end up in the &lt;code&gt;.vscode/&lt;/code&gt; directory that shouldn't be committed, so ignoring the files in this directory as a default is a good idea, but the &lt;code&gt;task.json&lt;/code&gt; and &lt;code&gt;launch.json&lt;/code&gt; files define build &amp;amp; run configurations that can (in my opinion, should) be shared with anyone cloning the project. They're not user specific files, so they're safe to add to your repository and will be tracked by default.&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging with ITM
&lt;/h2&gt;

&lt;p&gt;Nothing really changes here since last time, so see &lt;a href="https://christopherjmcclellan.wordpress.com/2019/11/29/debugging-rust-arm-cortexm-programs-with-visual-studio-code/#logging"&gt;the logging section of the original post&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using other hardware
&lt;/h2&gt;

&lt;p&gt;This is where we need to take an actual hard look at the &lt;code&gt;launch.json&lt;/code&gt; configuration and you'll also need a pretty good understanding of the hardware you wish to use, so if you're happily debugging your STM32F3DISCOVERY, feel free to stop here. However, if you're looking to setup VS Code for some other board, continue on and I'll do my best to explain what the different parts of the &lt;code&gt;Debug (OpenOCD)&lt;/code&gt; config do. For full documentation, see the Cortex-Debug &lt;a href="https://marcelball.ca/projects/cortex-debug/"&gt;project site&lt;/a&gt; and &lt;a href="https://github.com/Marus/cortex-debug"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For reference, here is the OpenOCD config for the STM32F303.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* Configuration for the STM32F303 Discovery board */&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cortex-debug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;launch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Debug (OpenOCD)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;servertype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openocd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cwd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;${workspaceRoot}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preLaunchTask&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;runToMain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./target/thumbv7em-none-eabihf/debug/cortexm-app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;device&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;STM32F303VCT6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;configFiles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;interface/stlink-v2-1.cfg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;target/stm32f3x.cfg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svdFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;${workspaceRoot}/.vscode/STM32F303.svd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swoConfig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cpuFrequency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swoFrequency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;probe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decoders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;console&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ITM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;port&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Server Type
&lt;/h3&gt;

&lt;p&gt;The Cortex-Debug extension supports a number of different GDB servers. Here, we're specifying that we're using OpenOCD.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"servertype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openocd"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you're using a different GDB server, you'll obviously need to &lt;a href="https://marcelball.ca/projects/cortex-debug/cortex-debug-launch-configurations/"&gt;reference the documentation&lt;/a&gt; to configure your server and most of the information below will be of questionable value to you.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Device
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STM32F303VCT6"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;device&lt;/code&gt; field is used to specify which MCU you're targeting and is used in conjunction with one of the several &lt;a href="https://marketplace.visualstudio.com/search?term=cortex-debug&amp;amp;target=VSCode&amp;amp;category=All%20categories&amp;amp;sortBy=Relevance"&gt;Cortex-Debug Device Support Packs&lt;/a&gt;. If you've installed the right pack and specified a device, the Cortex-Debug extension will use this field to look up the right SVD file for you and you can then omit the &lt;code&gt;svdFile&lt;/code&gt; field.&lt;br&gt;
So, technically, in the current configuration, this does nothing but document which microcontroller this config is meant for.&lt;/p&gt;
&lt;h3&gt;
  
  
  SVD File
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"svdFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}/.vscode/STM32F303.svd"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Specifies where the &lt;a href="https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html"&gt;System View Description&lt;/a&gt; for your device is located. As we've covered, this allows the Cortex-Debug plugin to load peripherals for your device into the editor. This can be omitted if using a Device Support Pack and &lt;code&gt;device&lt;/code&gt; field.&lt;/p&gt;
&lt;h3&gt;
  
  
  Config Files
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"configFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"interface/stlink-v2-1.cfg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"target/stm32f3x.cfg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is an array of config files passed to &lt;code&gt;openocd&lt;/code&gt; and equivalent to using the &lt;code&gt;-f&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;openocd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; interface/stlink-v2-1.cfg &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; target/stm32f3x.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you find your &lt;code&gt;openocd&lt;/code&gt; installation directory, you will find many common configurations and targets under the &lt;code&gt;share/openocd/scripts/&lt;/code&gt; directory. Specify the correct files for your device here.&lt;/p&gt;

&lt;h3&gt;
  
  
  SWO Config
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"swoConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpuFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"swoFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"probe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"decoders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ITM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This configures the &lt;code&gt;ITM&lt;/code&gt; output for the device. The fields you'll likely need to update here are the &lt;code&gt;cpuFrequency&lt;/code&gt;, &lt;code&gt;swoFrequency&lt;/code&gt;, and the ITM &lt;code&gt;port&lt;/code&gt;. Get any of these wrong and you'll not see any output in the &lt;code&gt;SWO&lt;/code&gt; output of the editor.&lt;/p&gt;

&lt;p&gt;Unfortunately, I can't help you much here. You'll need to reference your datasheet and schematic for the CPU frequency, as well as know what SWO frequency and port the software is using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I couldn't be happier that these configurations were added to the quickstart template. Hopefully, this lowers the barrier just that much more for folks looking to get into embedded Rust. I have high hopes for Rust as an embedded development language over the next decade. I figure the lower the bar to entry is, the more people we can get involved, the more likely it will be that we can develop the ecosystem into something that makes Rust a default choice for systems programming. I know it won't happen over night, and the languages currently in use aren't ever going away, but I'm happy to contribute one small piece in the puzzle to a better future for embedded software.&lt;/p&gt;

&lt;p&gt;Until next time,&lt;br&gt;
Semper Cogitet&lt;/p&gt;

</description>
      <category>rust</category>
      <category>arm</category>
      <category>embedded</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Debugging Rust ARM CortexM Programs with Visual Studio Code</title>
      <dc:creator>Christopher McClellan</dc:creator>
      <pubDate>Fri, 29 Nov 2019 19:10:30 +0000</pubDate>
      <link>https://dev.to/rubberduck/debugging-rust-arm-cortexm-programs-with-visual-studio-code-336h</link>
      <guid>https://dev.to/rubberduck/debugging-rust-arm-cortexm-programs-with-visual-studio-code-336h</guid>
      <description>&lt;h1&gt;
  
  
  Debugging Rust ARM CortexM Programs with Visual Studio Code
&lt;/h1&gt;

&lt;p&gt;I've been toying with embedded Rust off and on for some time now.&lt;br&gt;
I picked up one of the STM Discovery boards and it's been an interesting novelty for me to be able to remotely debug code running on the microcontroller. I've never been willing to spring for the external hardware debugger required to do so, but the Discovery has a STLink built into the board. The &lt;a href="https://rust-embedded.github.io/book/" rel="noopener noreferrer"&gt;Rust Embedded&lt;/a&gt; and &lt;a href="https://rust-embedded.github.io/discovery/" rel="noopener noreferrer"&gt;Discovery&lt;/a&gt; books have great instructions for remote debugging Rust programs, but rely soley on command line tools for doing so. I like the terminal as much as, if not more, than the next person, but it's also really nice to be able to set breakpoints and step through code right inside of the editor.&lt;/p&gt;

&lt;p&gt;I tend to use VS Code as my main editor these days, so that's what we'll set up today. We'll take a look at the hardware and setting up the toolchain first, before moving on to setting up our editor. The prior is essentially a condensed version of the information in &lt;a href="https://rust-embedded.github.io/discovery/" rel="noopener noreferrer"&gt;the Discovery book&lt;/a&gt;, so if you've already worked your way through that, feel free to skip to setting up VS Code.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Hardware
&lt;/h2&gt;

&lt;p&gt;This is the &lt;a href="https://www.st.com/en/evaluation-tools/stm32f3discovery.html#" rel="noopener noreferrer"&gt;STM32F3DISCOVERY&lt;/a&gt; board by ST.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.st.com/en/evaluation-tools/stm32f3discovery.html#" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.st.com%2Fbin%2Fecommerce%2Fapi%2Fimage.PF254044.en.feature-description-include-personalized-no-cpn-large.jpg" alt="green pcb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has a 32 bit ARM CortexM4 processor and, as I mentioned earlier, a super convenient built in debugger. It's a really nice little board. The mcu itself has 256kb flash memory and 48kb RAM while the eval board also has an accelerometer, magnetometer, gryroscope, and lots of built in leds, IO, and peripherals to play with. To top it all off, its $16 price point brings it in as less expensive than the official Arduino Uno with its 32kb flash memory, 2kb RAM, and lack of any additional trinkets. To be fair the STM32F303VCT6 microcontroller costs 3 times the Uno's ATMega328p and is quite a bit more complex, but I really like this board.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing the toolchain
&lt;/h2&gt;

&lt;p&gt;Below is a summary of the &lt;a href="https://docs.rust-embedded.org/discovery/03-setup/index.html" rel="noopener noreferrer"&gt;instructions in the Discovery book for setting up your environment for ARM development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, install the necessary build targets and extra &lt;code&gt;cargo&lt;/code&gt; tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# itmdump&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;itm

&lt;span class="c"&gt;# bin-utils&lt;/span&gt;
rustup component add llvm-tools-preview
rustup target add thumbv7em-none-eabihf
cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-binutils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install the actual ARM toolchain itself.&lt;/p&gt;

&lt;p&gt;If you're using Mac, be sure to use the instructions from the &lt;a href="https://rust-embedded.github.io/book/intro/install/macos.html" rel="noopener noreferrer"&gt;Rust Embedded Book&lt;/a&gt;. There have been multiple pull requests open to fix this in the Discovery book for a little while now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap ArmMbed/homebrew-formulae
brew &lt;span class="nb"&gt;install &lt;/span&gt;arm-none-eabi-gcc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;openocd&lt;/code&gt;, we'll be using it to flash and debug our Discovery board.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;openocd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect the board to your laptop via the STLink USB port and verify you can connect via &lt;code&gt;openocd&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;openocd &lt;span class="nt"&gt;-f&lt;/span&gt; interface/stlink-v2-1.cfg &lt;span class="nt"&gt;-f&lt;/span&gt; target/stm32f3x.cfg
&lt;span class="go"&gt;Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
&lt;/span&gt;&lt;span class="gp"&gt;Info : auto-selecting first available session transport "hla_swd". To override use 'transport select &amp;lt;transport&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'.
&lt;/span&gt;&lt;span class="go"&gt;adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.900414
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone the Discovery repository and build the &lt;code&gt;led-roulette&lt;/code&gt; example (it's not actually a led-roulette at this point, but it's a good example for using the &lt;code&gt;gdb&lt;/code&gt; debugger).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/rust-embedded/discovery.git
&lt;span class="nb"&gt;cd &lt;/span&gt;discovery/src/05-led-roulette/
cargo build &lt;span class="nt"&gt;--target&lt;/span&gt; thumbv7em-none-eabihf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Making sure &lt;code&gt;openocd&lt;/code&gt; is still running in another terminal, connect to the device with &lt;code&gt;gdb&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Note: If you're running Linux or Windows, or installed the ARM toolchain without &lt;code&gt;homebrew&lt;/code&gt;, the &lt;code&gt;gdb&lt;/code&gt; command may be slightly different. See the &lt;a href="https://rust-embedded.github.io/discovery/05-led-roulette/flash-it.html" rel="noopener noreferrer"&gt;"Flash It" section of the Discovery book&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;arm-none-eabi-gdb &lt;span class="nt"&gt;-q&lt;/span&gt; target/thumbv7em-none-eabihf/debug/led-roulette
&lt;span class="go"&gt;Reading symbols from target/thumbv7em-none-eabihf/debug/led-roulette
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will drop you into a &lt;code&gt;gdb&lt;/code&gt; shell where you can execute the following commands to connect to the target, load the executable, set a breakpoint, and generally debug the code, with &lt;a href="https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf" rel="noopener noreferrer"&gt;gdb commands&lt;/a&gt; like &lt;code&gt;next&lt;/code&gt; and &lt;code&gt;step&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;(gdb) target remote :3333
Remote debugging using :3333
0x00000000 in ?? ()
(gdb) load
Loading section .vector_table, size 0x188 lma 0x8000000
Loading section .text, size 0x4102 lma 0x8000188
Loading section .rodata, size 0xf20 lma 0x8004290
Start address 0x8003df0, load size 20906
Transfer rate: 19 KB/sec, 5226 bytes/write.
(gdb) break main
Breakpoint 1 at 0x800018c: file src/05-led-roulette/src/main.rs, line 9.
(gdb) continue
(gdb) layout src
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.rust-embedded.org%2Fdiscovery%2Fassets%2Fgdb-layout-src.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.rust-embedded.org%2Fdiscovery%2Fassets%2Fgdb-layout-src.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving the Terminal Experience
&lt;/h2&gt;

&lt;p&gt;Eventually we'll want to use the built in debugging capabilities of VS Code, but first let's make a few adjustments to our &lt;code&gt;cargo&lt;/code&gt; configuration to make our lives a bit easier.&lt;/p&gt;

&lt;p&gt;First, we'll script our &lt;code&gt;gdb&lt;/code&gt; session to automatically load the latest code and advance us to main instead of pre-init.&lt;/p&gt;

&lt;h3&gt;
  
  
  openocd.gdb
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;target remote :3333
load
break main
continue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can update our &lt;code&gt;.cargo\config&lt;/code&gt; to use this script as part of the runner, as well as set the default build target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[target.thumbv7em-none-eabihf]&lt;/span&gt;
&lt;span class="py"&gt;runner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"arm-none-eabi-gdb -q -x openocd.gdb"&lt;/span&gt;
&lt;span class="py"&gt;rustflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"link-arg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;-Tlink.x&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"thumbv7em-none-eabihf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we run &lt;code&gt;cargo run&lt;/code&gt;, we'll automatically build for the correct target and run our &lt;code&gt;gdb&lt;/code&gt; script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cargo run
&lt;span class="go"&gt;   Compiling led-roulette v0.1.0 (/Users/rubberduck/src/discovery/src/05-led-roulette)
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
     Running `arm-none-eabi-gdb -q -x openocd.gdb /Users/rubberduck/src/discovery/target/thumbv7em-none-eabihf/debug/led-roulette`
Reading symbols from /Users/rubberduck/src/discovery/target/thumbv7em-none-eabihf/debug/led-roulette...
main () at src/05-led-roulette/src/main.rs:10
&lt;/span&gt;&lt;span class="gp"&gt;10          let x = 42;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;Loading section .vector_table, size 0x188 lma 0x8000000
Loading section .text, size 0x66a lma 0x8000188
Loading section .rodata, size 0x2c4 lma 0x8000800
Start address 0x8000196, load size 2742
Transfer rate: 8 KB/sec, 914 bytes/write.
Breakpoint 1 at 0x800018c: file src/05-led-roulette/src/main.rs, line 10.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at src/05-led-roulette/src/main.rs:10
&lt;/span&gt;&lt;span class="gp"&gt;10          let x = 42;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;(gdb) 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up Visual Studio Code
&lt;/h2&gt;

&lt;p&gt;We'll need a couple of extensions from the marketplace. &lt;br&gt;
Go ahead and install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=rust-lang.rust" rel="noopener noreferrer"&gt;Rust Language Server&lt;/a&gt; and &lt;a href="https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug" rel="noopener noreferrer"&gt;Cortex-Debug&lt;/a&gt; extensions from the marketplace.&lt;/p&gt;

&lt;p&gt;Next, we'll add a new launch configuration.&lt;/p&gt;
&lt;h3&gt;
  
  
  .vscode/launch.json
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cortex-debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"servertype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openocd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"executable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./target/thumbv7em-none-eabihf/debug/led-roulette"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Debug (OpenOCD)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STM32F303VCT6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"configFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"interface/stlink-v2-1.cfg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"target/stm32f3x.cfg"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runToMain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice that the &lt;code&gt;configFiles&lt;/code&gt; property contains the same list of files that we passed to &lt;code&gt;openocd&lt;/code&gt; earlier. Ensure you've stopped &lt;code&gt;openocd&lt;/code&gt; in the other terminal, run the default build task (&lt;code&gt;CMD + Shift + B&lt;/code&gt;), and then start the debug session. The code will break just inside of the &lt;code&gt;main&lt;/code&gt; method. You're currently debugging the code running on the Discovery board from VS Code! You can step over and into the code, as well as see the current values of the individual registers under "CORTEX REGISTERS".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqsnz5aju3oi8jqyte8em.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqsnz5aju3oi8jqyte8em.png" alt="No SVD File Loaded:/Users/rubberdu..."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may notice that there is also a "CORTEX PERIPHERALS" section in the debug sidebar, but it says "No SVD File Loaded: undefined". Let's fix that now. &lt;a href="https://www.st.com/resource/en/svd/stm32f3_svd.zip" rel="noopener noreferrer"&gt;Download the SVD files&lt;/a&gt; and extract them. Copy &lt;code&gt;STM32F303.svd&lt;/code&gt; into the &lt;code&gt;src/05-led-roulette&lt;/code&gt; directory and add the following line to the &lt;code&gt;launch.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cortex-debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"servertype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openocd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"svdFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}/STM32F303.svd"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next time you start the debugger, you'll now see all of the STM32F303's peripherals loaded. You can even directly write hex values to them!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7hi14eb7yvnff0j61h26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7hi14eb7yvnff0j61h26.png" alt="Peripherals and Registers listed. Hex values ready to write in command bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging
&lt;/h2&gt;

&lt;p&gt;The ARM Cortex M3 series has an Instrumentation Trace Macrocell (ITM) for sending log statements via the debugger. The Rust &lt;code&gt;itm&lt;/code&gt; and &lt;code&gt;panic-itm&lt;/code&gt; crates use this to send &lt;code&gt;println&lt;/code&gt; and panic messages back to your development machine. Doing this from the terminal is described in &lt;a href="https://docs.rust-embedded.org/discovery/06-hello-world/index.html" rel="noopener noreferrer"&gt;Chapter 6: Hello World&lt;/a&gt; of the Discovery book. It's worth while running through that excercise before the next section. Note that you either need to jump pins &lt;code&gt;SWO&lt;/code&gt; and &lt;code&gt;PB3&lt;/code&gt; or close solder bridge &lt;code&gt;SB10&lt;/code&gt; on the underside of the board. I opted for the latter as it's a pretty simple job to solder the bridge closed. If you're uncomfortable with, or don't have a solder iron, don't worry, the jumper wire works just fine too.&lt;/p&gt;

&lt;p&gt;You're back? Awesome! Let's integrate &lt;code&gt;itm&lt;/code&gt; into our editor too!&lt;/p&gt;

&lt;p&gt;Copy &lt;code&gt;.vscode/launch.json&lt;/code&gt; and &lt;code&gt;.cargo/config&lt;/code&gt; from the &lt;code&gt;05-led-roulette&lt;/code&gt; directory into the &lt;code&gt;06-hello-world&lt;/code&gt; directory. Then modify the executable path and add the following &lt;code&gt;swoConfig&lt;/code&gt; to your &lt;code&gt;launch.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  launch.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"executable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./target/thumbv7em-none-eabihf/debug/hello-world"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"swoConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpuFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"swoFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"probe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"decoders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ITM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is essentially equivalent to the &lt;code&gt;gdb&lt;/code&gt; commands we ran from the Discovery book.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;(gdb) #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;globally &lt;span class="nb"&gt;enable &lt;/span&gt;the ITM and redirect all output to itm.txt
&lt;span class="go"&gt;(gdb) monitor tpiu config internal itm.txt uart off 8000000

&lt;/span&gt;&lt;span class="gp"&gt;(gdb) #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable &lt;/span&gt;the ITM port 0
&lt;span class="go"&gt;(gdb) monitor itm port 0 on
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We enable the monitor, tell the debugger that the CPU is running at 8MHz (the default clock speed for the STM32F303x controllers) and connect to &lt;code&gt;ITM&lt;/code&gt; port &lt;code&gt;0&lt;/code&gt; at 2MHz.  Instead of writing the output to a specific file, the Cortex-Debug extension will create a new temporary file for us.&lt;/p&gt;

&lt;p&gt;Build the program and begin debugging. &lt;br&gt;
Navigate to the OUTPUT and select the &lt;code&gt;SWO: ITM[port:0, type: console]&lt;/code&gt; output.&lt;br&gt;
Step over the &lt;code&gt;iprintln&lt;/code&gt; and you'll see the message written to the log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7eozetff2wdpkojk6yjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7eozetff2wdpkojk6yjh.png" alt="[2019-11-29T17:55:24.140Z]   Hello, world!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run &lt;a href="https://docs.rust-embedded.org/discovery/06-hello-world/panic.html" rel="noopener noreferrer"&gt;the panic example&lt;/a&gt;, you'll see the panic message printed to the log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2019-11-29T18:04:58.320Z]   panicked at 'Hello, world!', src/06-hello-world/src/main.rs:19:5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automatically Build Before Uploading/Debugging
&lt;/h2&gt;

&lt;p&gt;Up until this point, we've had to manually run &lt;code&gt;cargo build&lt;/code&gt; prior to debugging any time we've changed the code. I've frustrated myself more than once by forgetting to do this, so I added a &lt;code&gt;preLaunchTask&lt;/code&gt; to automatically build before upload. The build task is just the default &lt;code&gt;cargo build&lt;/code&gt; task, but we need to add a label to it to be able to reference it from &lt;code&gt;launch.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  .vscode/tasks.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cargo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subcommand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"problemMatcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"$rustc"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isDefault"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .vscode/launch.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"preLaunchTask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we press the "play" button to debug, we ensure we've compiled the latest version of our code first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Config Files
&lt;/h2&gt;

&lt;p&gt;That's about it. We have a fully functioning development environment in VS Code. Complete config files are below. Enjoy!&lt;/p&gt;

&lt;h3&gt;
  
  
  .vscode/tasks.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cargo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"subcommand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"problemMatcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"$rustc"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"isDefault"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .vscode/launch.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cortex-debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Debug (OpenOCD)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"servertype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openocd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"executable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./target/thumbv7em-none-eabihf/debug/compass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"preLaunchTask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STM32F303VCT6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"configFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"interface/stlink-v2-1.cfg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"target/stm32f3x.cfg"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"svdFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}/STM32F303.svd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runToMain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"swoConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"cpuFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"swoFrequency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"probe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"decoders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ITM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .cargo/config
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[target.thumbv7em-none-eabihf]&lt;/span&gt;
&lt;span class="c"&gt;# Not used by the VS Code Debugger, only `cargo run`&lt;/span&gt;
&lt;span class="py"&gt;runner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"arm-none-eabi-gdb -q -x openocd.gdb"&lt;/span&gt;
&lt;span class="py"&gt;rustflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"link-arg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;-Tlink.x&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"thumbv7em-none-eabihf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  openocd.gdb
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Not used by the VS Code Debugger, only `cargo run`&lt;/span&gt;
target remote :3333
&lt;span class="nb"&gt;set &lt;/span&gt;print asm-demangle on
&lt;span class="nb"&gt;set &lt;/span&gt;print pretty on
load
monitor tpiu config internal itm.txt uart off 8000000
monitor itm port 0 on
&lt;span class="nb"&gt;break &lt;/span&gt;main
&lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rust</category>
      <category>embedded</category>
      <category>vscode</category>
      <category>arm</category>
    </item>
    <item>
      <title>Using USB with Docker for Mac</title>
      <dc:creator>Christopher McClellan</dc:creator>
      <pubDate>Sun, 21 Apr 2019 13:37:50 +0000</pubDate>
      <link>https://dev.to/rubberduck/using-usb-with-docker-for-mac-3fdd</link>
      <guid>https://dev.to/rubberduck/using-usb-with-docker-for-mac-3fdd</guid>
      <description>&lt;p&gt;If you've been struggling with this issue and just want an answer, skip to the bottom for the TL;DR. I won't fault you for it.&lt;/p&gt;

&lt;p&gt;Docker is a great tool for deploying web services, but one of my favorite uses for it is standardizing toolchains. Instead of everyone on the team needing to setup their development environments identically, and then keep them in sync, you define the build tools in a single place, a docker image. Then everyone, including your build server, uses that single pre-packaged image.&lt;/p&gt;

&lt;p&gt;Not only is this great for teams, but it's also fantastic when you have side projects that you only periodically revisit. Without fail, when I come back to some old project, I've since updated my tools for something newer, and I can't build that old project without either upgrading the project or degrading my tools. Leaving a build tools image behind means I can just pick it up and work on it without spending a day getting back up and running.&lt;/p&gt;

&lt;p&gt;It's not all sunshine and roses though. I went on quite an adventure today. Last year I put on a &lt;a href="https://christopherjmcclellan.wordpress.com/?p=2103"&gt;TDD for Arduino workshop&lt;/a&gt;. I had started to create &lt;a href="https://hub.docker.com/r/rubberduck/avr/"&gt;a Docker image for AVR development&lt;/a&gt;,  but ran into problems when it came time to flash the program to the board. Exposing a USB port to a docker container on Mac isn't exactly a trivial task (until you know how at least!). For that session we mobbed, so I only had to setup one machine. I just stopped fighting with it and went with a regular install of the tools on my machine.&lt;/p&gt;

&lt;p&gt;Recently though, I've taken a renewed interest in getting this to work properly. First, I've been playing with ARM development, but &lt;a href="https://bugs.launchpad.net/ubuntu/+source/gcc-avr/+bug/1746955"&gt;there's a bug in AVR and ARM's compiler packaging that means you can't have both toolchains installed at the same time&lt;/a&gt;. Having these toolchains containerized means I can easily keep both readily available. Secondly, I'm now beginning to build on that workshop to turn it into an "Intro to Bare Metal Programming" course. For that, I really need to be able to hand folks an environment I know works, so we're not spending more time working kinks out of dev setups than learning. Also, in order to standardize embedded toolchains for a team or client at work, I really need to know how to get USB working on Mac.&lt;/p&gt;

&lt;p&gt;If you're running Linux, this is as simple as adding &lt;code&gt;--device /dev/ttyUSBx&lt;/code&gt; to the docker run command. Needless to say, it's not that simple on OSX or Windows. That's because the docker daemon only runs natively on Linux. For other operating systems it's run in a hypervisor or virtual machine. In order to expose the port to the container, you first have to expose it to the virtual machine where Docker is running. Unfortunately, &lt;a href="https://github.com/docker/for-mac/issues/900"&gt;hyperkit, the hypervisor that Docker-For-Mac uses doesn't support USB forwarding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we can't expose a USB port to the native Mac Docker hypervisor, we have to fallback onto &lt;code&gt;docker-machine&lt;/code&gt;, which uses a Virtualbox VM to host the &lt;code&gt;dockerd&lt;/code&gt; daemon. There are &lt;a href="http://gw.tnode.com/docker/docker-machine-with-usb-support-on-windows-macos/"&gt;great instructions for setting up docker-machine with a USB filter&lt;/a&gt;, but I was getting a lot of mysterious segfaults from &lt;code&gt;docker-machine&lt;/code&gt; that would leave my VM running, but also unable to recover a connection to it through docker-machine. It turns out that &lt;a href="https://milad.ai/docker/2018/05/06/access-usb-devices-in-container-in-mac.html#comment-4370651082"&gt;several versions of VirtualBox had a bug causing the segfaults&lt;/a&gt;. Upgrading to v6.06 solved that problem, but I still couldn't see the device. It took me too long to remember that I had the same trouble with USB 3.0 a few months ago with a Windows guest OS. Dropping down to USB 2.0 fixed that issue.&lt;/p&gt;

&lt;p id="tldr"&gt;Okay, let's get down to business and get a fully containerized embedded toolchain running on Mac.&lt;/p&gt;

&lt;p&gt;First, &lt;a href="https://www.virtualbox.org/wiki/Downloads"&gt;download and install VirtualBox version 6.06 or greater&lt;/a&gt;. Again, this must be version 6.06 or greater or you'll see segfaults when trying to create a USB filter later. You can optionally install &lt;a href="https://download.virtualbox.org/virtualbox/6.0.6/Oracle_VM_VirtualBox_Extension_Pack-6.0.6.vbox-extpack"&gt;the VirtualBox extension pack&lt;/a&gt;. I recommend it though, because it enables USB 2.0, which results in faster programming times.&lt;/p&gt;

&lt;p&gt;Next, we can create and setup our &lt;code&gt;docker-machine&lt;/code&gt; (virtual machine).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#! /bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#create and start the machine&lt;/span&gt;
docker-machine create &lt;span class="nt"&gt;-d&lt;/span&gt; virtualbox default

&lt;span class="c"&gt;#We must stop the machine in order to modify some settings&lt;/span&gt;
docker-machine stop

&lt;span class="c"&gt;#Enable USB&lt;/span&gt;
vboxmanage modifyvm default &lt;span class="nt"&gt;--usb&lt;/span&gt; on

&lt;span class="c"&gt;# OR, if you installed the extension pack, use USB 2.0&lt;/span&gt;
vboxmanage modifyvm default &lt;span class="nt"&gt;--usbehci&lt;/span&gt; on

&lt;span class="c"&gt;# Go ahead and start the VM back up&lt;/span&gt;
docker-machine start

&lt;span class="c"&gt;# Official Arduinos and many clones use an FTDI chip.&lt;/span&gt;
&lt;span class="c"&gt;# If you're using a clone that doesn't, &lt;/span&gt;
&lt;span class="c"&gt;# or are setting this up for some other purpose&lt;/span&gt;
&lt;span class="c"&gt;# run this to find the vendor &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; product id for your device.&lt;/span&gt;
&lt;span class="c"&gt;# vboxmanage list usbhost&lt;/span&gt;

&lt;span class="c"&gt;# Setup a usb filter so your device automatically gets connected to the Virtualbox VM.&lt;/span&gt;
vboxmanage usbfilter add 0 &lt;span class="nt"&gt;--target&lt;/span&gt; default &lt;span class="nt"&gt;--name&lt;/span&gt; ftdi &lt;span class="nt"&gt;--vendorid&lt;/span&gt; 0x0403 &lt;span class="nt"&gt;--productid&lt;/span&gt; 0x6015

&lt;span class="c"&gt;#setup your terminal to use your new docker-machine&lt;/span&gt;
&lt;span class="c"&gt;#(you must do this every time you want to use this docker-machine or add it to your bash profile)&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker-machine &lt;span class="nb"&gt;env &lt;/span&gt;default&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now go ahead and plug in your device and run this command to verify that containers can see it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/ttyUSB0 ubuntu:18.04 bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"ls /dev/ttyUSB0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the command fails, make sure your device is plugged in and visible to the VM. You may have mistyped the vendor and product ids, or the tty may be attached under a different number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-machine ssh default &lt;span class="s2"&gt;"ls /dev/tty*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it. Like I said, it's really easy once you know how. Unfortunately, there's not official documentation and, considering that both &lt;code&gt;docker-machine&lt;/code&gt; and &lt;code&gt;boot2docker&lt;/code&gt; are in maintenance mode, I'm hoping we get official support for USB on hyperkit in the future. Containerizing build tools is a great way for teams to take advantage of the technology even if you're not using them to deploy services. Now, if you'll excuse me, I need to go update my AVR toochain image with a script to do this and add in &lt;code&gt;avrdude&lt;/code&gt; for uploading programs.&lt;/p&gt;

&lt;p&gt;Until next time,&lt;br&gt;
Semper Cogitet&lt;/p&gt;

</description>
      <category>docker</category>
      <category>mac</category>
      <category>embedded</category>
      <category>arduino</category>
    </item>
    <item>
      <title>Test Driving Arduino</title>
      <dc:creator>Christopher McClellan</dc:creator>
      <pubDate>Fri, 16 Feb 2018 03:36:33 +0000</pubDate>
      <link>https://dev.to/rubberduck/test-driving-arduino--35l4</link>
      <guid>https://dev.to/rubberduck/test-driving-arduino--35l4</guid>
      <description>&lt;p&gt;Originally posted on &lt;a href="https://christopherjmcclellan.wordpress.com/2018/02/16/test-driving-arduino/" rel="noopener noreferrer"&gt;christopherjmcclellan.wordpress.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I gave a workshop for the &lt;a href="http://www.colug.net/carpe/" rel="noopener noreferrer"&gt;Columbus Arduino and Raspberry Pi Enthusiasts&lt;/a&gt; (CARPE) Tuesday night. We had a great time and I thought it would be a good idea to share the experience and my motivation creating the workshop here.&lt;/p&gt;

&lt;p&gt;The Arduino IDE isn't what I'd call good. It's great for someone new to programming or microcontrollers. It gets you from zero to blinking a light in seconds, but lacks a lot of features that seasoned programmers rely on. It has a myriad of problems.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;No file browser.&lt;/li&gt;
    &lt;li&gt;No terminal.&lt;/li&gt;
    &lt;li&gt;No code navigation (like "Go to declaration").&lt;/li&gt;
    &lt;li&gt;Code is hidden away where it's hard find and get into source control.&lt;/li&gt;
    &lt;li&gt;No way to create automated unit tests.&lt;/li&gt;
    &lt;li&gt;Arduino libs aren't always well behaved (SoftwareSerial and OneWire are notorious for globally disabling interrupts).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few months ago I set out to see if I could some of these problems. My main goal was to be able to TDD microcontroller code. The secondary goal was to be able to use whichever editor I liked. I figured I would probably &lt;em&gt;need&lt;/em&gt; to use a different editor anyway.&lt;/p&gt;

&lt;p&gt;Before I got started, I picked up a copy of &lt;a href="https://pragprog.com/book/jgade/test-driven-development-for-embedded-c" rel="noopener noreferrer"&gt;"Test Driven Development For Embedded C" by James Grenning&lt;/a&gt;. I wanted to know if what I wanted to do was even possible before I got started. It turns out that it's largely very testable, even if not many people out there are doing TDD for embedded systems. There are some things that are legitimately hard to test, but I'll get to that later.&lt;/p&gt;

&lt;p&gt;James gives an example of doing TDD for a LED Driver in the book. That inspired me to create the &lt;a href="https://github.com/rubberduck203/led-driver-kata" rel="noopener noreferrer"&gt;LED Driver Kata&lt;/a&gt;. The premise is pretty simple. You need to create a LED driver to light up some LEDs memory mapped to an 8 bit register. The problem is, the hardware isn't ready yet. How do we write and, perhaps more importantly, &lt;em&gt;test&lt;/em&gt; code for hardware that doesn't exist yet? James gives examples in his book, but the most important for me was the idea of faking the register out by passing a reference to an unsigned integer to the driver. This allows us not only to observe the results of the code, but also means the driver code isn't dependent on the hardware. It looks something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;TEST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LedDriverTests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TurnAllLedsOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;leds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;LedsOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;leds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;BYTES_EQUAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;leds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other core concept is &lt;em&gt;cross-compiling&lt;/em&gt; your code. The code under test gets compiled along with your tests for the &lt;em&gt;host&lt;/em&gt; machine. Your tests run on your development machine. Once the tests pass, then you compile for the &lt;em&gt;target&lt;/em&gt; device's architecture.&lt;/p&gt;

&lt;p&gt;Now that I knew it was indeed feasible to test drive embedded code, I set out to implement the kata.&lt;/p&gt;

&lt;p&gt;The secret here is that Arduino is built on top of the pre-existing &lt;a href="http://www.nongnu.org/avr-libc/" rel="noopener noreferrer"&gt;AVR toolchain&lt;/a&gt;. Arduino uses the avr-gcc compiler and AVRDude under the hood to compile and upload to the board. You can see this yourself by going to File -&amp;gt; Preferences and selecting the "Show Verbose Output" options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2Fscreen-shot-2018-02-15-at-7-53-04-pm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2Fscreen-shot-2018-02-15-at-7-53-04-pm.png" alt="Show verbose output during [x] compilation [x] upload"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Arduino installs the toolchain inside it's application directory, but I found it convenient to just install the tools separately. If you're running Windows, the toolchain is available via &lt;a href="https://sourceforge.net/projects/winavr/" rel="noopener noreferrer"&gt;WinAVR&lt;/a&gt;. If you're running a *nix system, just go check out the &lt;a href="https://github.com/rubberduck203/avr" rel="noopener noreferrer"&gt;AVR docker image&lt;/a&gt; I created. It lists out the different apt packages you'll need, including the CppUTest testing framework.&lt;/p&gt;

&lt;p&gt;I started out compiling by hand, but it didn't take me long to start fumbling my way through creating a Makefile. In fact, the first time I did the kata, I spent far more time working on crafting a Makefile than I did working on the code. The LED Driver kata turned out to be 2 katas in one. Thankfully, I only needed to work that out once. I turned that Makefile into a &lt;a href="https://github.com/rubberduck203/avr-template" rel="noopener noreferrer"&gt;reusable template for all my AVR projects&lt;/a&gt;. Just clone the project add some code. I've actually been using this setup for the &lt;a href="https://github.com/rubberduck203/digital-thermometer" rel="noopener noreferrer"&gt;digital thermometer I'm building&lt;/a&gt; too. It works really well.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;I can use any text editor and terminal.&lt;/li&gt;
    &lt;li&gt;I've TDD'ed &lt;em&gt;most&lt;/em&gt; of the implementation.&lt;/li&gt;
    &lt;li&gt;No worries about Arduino libs misbehaving, because I'm not using them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a few downsides to this approach though.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;No Arduino libs + no Arduino IDE means no serial monitor. To be honest though, I've rarely missed it because I have a test suite.&lt;/li&gt;
    &lt;li&gt;Not everything is unit testable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, consider some external device that requires a very quick pin pulse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ShiftRegister&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;pulse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;bitmask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// pull the pin high to clock the data,&lt;/span&gt;
    &lt;span class="c1"&gt;// then back to low so we choose when to send it.&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataOut&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;bitmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataOut&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;bitmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's no way to observe the side effect from the test. By time the test has finished executing, the register is back in its original state. I suppose this could be solved with a layer of indirection and some mocking, but the code is obviously correct by sight. I'm okay with leaving this as it is.&lt;/p&gt;

&lt;p&gt;Anyway, that's a fairly long winded way of providing some context for what we did at the workshop the other night. I cloned a fresh copy of the template and introduced the group to the kata. Next I gave them the rules of the game. We'd be Mob Programming the kata together. The person at the keyboard would type what the group told them to type. That person isn't allowed to think. If they have an idea, they must give the keyboard to someone else and instruct that person on what to type next. When we were done, we'd upload it to an Arduino hooked up to a bank of 8 LEDs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2F8-led-bank.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2F8-led-bank.png" alt="8 LED Bank"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got the group started by writing the first test. Things were a bit bumpy out of the gate. I was live coding in front of an audience after a full day's work and couldn't get the test to pass. After a few minutes someone pointed out that I was setting the value to the exact &lt;em&gt;opposite&lt;/em&gt; of the expected value. I thanked him, laughed, and passed off the keyboard. People were very hesitant at first, but pretty soon the group had found their rhythm. One by one tests would go red then green. Once in a while I'd interject with some insight or a refactor to try.&lt;/p&gt;

&lt;p&gt;Eventually I wasn't paying much attention to the code at all. I started wandering around talking to the folks who were a bit too reserved to actively participate. I found there was an interesting mix of questions. Some people were asking me about TDD, some about microcontrollers and embedded programming. There were very few people in the room who had done both and, as far as I could tell, none who had done TDD with embedded C++.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2Fimg_1419.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchristopherjmcclellan.files.wordpress.com%2F2018%2F02%2Fimg_1419.jpg" alt="Group of people programming together in harmony"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suddenly I heard "Hey Chris! We're done! How do we upload this thing to the board?" They took me by surprise. Before we started, I was worried that we wouldn't have time to finish the kata. I ran back to the keyboard and wrote a quick loop in the main to flash the lights in sequence, then burned the program. It worked. &lt;strong&gt;It. Just. Worked.&lt;/strong&gt; We all kind of marveled at the power of the mob and TDD for a moment as our device driver worked the &lt;em&gt;very first&lt;/em&gt; time we flashed it to the board.&lt;/p&gt;

&lt;p&gt;Well... it &lt;em&gt;almost&lt;/em&gt; worked. There was one light that wasn't lighting up. I instantly suspected the loop I wrote without any tests, but then someone piped up, "The code works. The tests pass and we all saw you write that loop. The code is right. It's a &lt;em&gt;hardware &lt;/em&gt;bug." By golly they were right too. We fiddled with the breadboard for just a moment before that stubborn little light lit up.&lt;/p&gt;

&lt;p&gt;This was precisely the point of the whole exercise. We &lt;em&gt;knew&lt;/em&gt; the code worked because every single line of code was tested and reviewed by an entire room full of programmers. This narrowed the search space for the bug down to the &lt;em&gt;only&lt;/em&gt; place it could have been. It was fixed within moments.&lt;/p&gt;

&lt;p&gt;I really couldn't be happier with how things went. Even though I screwed up by live coding instead of preparing the first test before hand, the power of collective problem solving and test driven development really shined through. Most importantly though, we proved that not only can embedded code be tested, but that people with little experience can do it if given the right tools and support.&lt;/p&gt;

</description>
      <category>arduino</category>
    </item>
    <item>
      <title>How to See Memory and CPU Usage for All Your Docker Containers (on CentOS 6)</title>
      <dc:creator>Christopher McClellan</dc:creator>
      <pubDate>Sat, 22 Jul 2017 19:43:50 +0000</pubDate>
      <link>https://dev.to/rubberduck/how-to-see-memory-and-cpu-usage-for-all-your-docker-containers</link>
      <guid>https://dev.to/rubberduck/how-to-see-memory-and-cpu-usage-for-all-your-docker-containers</guid>
      <description>&lt;p&gt;&lt;a href="https://christopherjmcclellan.wordpress.com/2017/07/22/docker-container-memory-usage/"&gt;&lt;em&gt;Originally posted on my blog.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I run a bunch of Docker containers on a single CentOS 6 server with a limited amount of memory. (I only recently bumped it from 0.5 to 1 whole whopping gig!)  Before I bring another container online, I like to check to see how much room I've got. Being the newest versions of Docker aren't available for CentOS 6, I'm running an ancient version, 1.7 or so. On the new versions of Docker, running  &lt;code&gt;docker stats&lt;/code&gt; will return statistics about all of your running container, but on old versions, you must pass &lt;code&gt;docker stats&lt;/code&gt; a container id. Here's a quick one-liner that displays stats for all of your running containers for old versions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-q&lt;/span&gt; | xargs  docker stats &lt;span class="nt"&gt;--no-stream&lt;/span&gt;
CONTAINER           CPU %               MEM USAGE/LIMIT     MEM %               NET I/O
31636c70b372        0.07%               130.8 MB/1.041 GB   12.57%              269.7 kB/262.8 kB
8d184dfbeeaf        0.00%               112.8 MB/1.041 GB   10.84%              45.24 MB/32.66 MB
a63b24fe6099        0.45%               50.09 MB/1.041 GB   4.81%               1.279 GB/1.947 GB
fd1339522e04        0.01%               108.2 MB/1.041 GB   10.40%              8.262 MB/23.36 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docker ps -q&lt;/code&gt; returns the list of running container ids, which we then pipe through &lt;code&gt;xargs&lt;/code&gt; and into &lt;code&gt;docker stats&lt;/code&gt;. Adding &lt;code&gt;--no-stream&lt;/code&gt; gives us just the first result instead of continually updating the stats, but this works just fine without it.&lt;/p&gt;

&lt;p&gt;It’s a neat little trick. If anyone knows how to make this return container names instead of ids, please comment below.&lt;/p&gt;

&lt;p&gt;Again, this is unnecessary for the newest versions. Just run &lt;code&gt;docker stats&lt;/code&gt; and you'll get nearly identical output.&lt;/p&gt;

&lt;p&gt;~Semper Cogitet&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
  </channel>
</rss>
