{"id":1018,"date":"2019-09-26T15:14:03","date_gmt":"2019-09-26T14:14:03","guid":{"rendered":"https:\/\/mightydevices.com\/?p=1018"},"modified":"2020-01-30T20:51:50","modified_gmt":"2020-01-30T19:51:50","slug":"stm32-development-env-for-windows-vscode-arm-gcc-toolchain-openocd","status":"publish","type":"post","link":"https:\/\/mightydevices.com\/index.php\/2019\/09\/stm32-development-env-for-windows-vscode-arm-gcc-toolchain-openocd\/","title":{"rendered":"STM32 Development Env for Windows: VSCode + ARM GCC Toolchain + OpenOCD"},"content":{"rendered":"\n<p>In this tutorial I&#8217;ll shortly describe how I setup my development environment for the STM32 micros. STM32L433 will be used as an example but the following process shall be applicable to any other STM32 micro.<\/p>\n\n\n\n<h2>Step 1: Get the Toolchain<\/h2>\n\n\n\n<p>In order to make the whole development process portable (i.e. to allow other parties to build the same output binary images from the same source files) I use <code>Docker<\/code> build <code>container<\/code>. If you aren&#8217;t familiar to Docker then go ahead and <a href=\"https:\/\/www.docker.com\/resources\/what-container\">read this article<\/a>. After that install <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\">Docker Desktop<\/a> on your computer. <\/p>\n\n\n\n<p>Although not strictly necessary three advantages come with the Docker approach: <\/p>\n\n\n\n<ul><li>Docker offers virtualization that ensures that other people who use the same Docker image will get she same results no matter what underlying (Host) OS they use, etc.. <\/li><li>Docker (if well configured) can make the firmware building process to go *much* faster than building within the HostOS due to the fact that we&#8217;ll be storing the build process half-products (like <code>*.o<\/code> files) within the file system of the container that resides in RAM<\/li><li>You don&#8217;t have to contaminate your Host OS with tools for building ARM projects<\/li><\/ul>\n\n\n\n<p>Next step would be to build the docker <code>image<\/code> on your machine.  Since i&#8217;ve put the docker image to the <code>dockerhub.io<\/code> (which is an image storing repository, something like <code>git<\/code>) the whole build process can be started by typing in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker pull twatorowski\/gcc-arm-none-eabi<\/code><\/pre>\n\n\n\n<p>If you are interested in the details of this image then take a peek at  <a href=\"https:\/\/github.com\/MightyDevices\/docker-gcc-arm-none-eabi-builder\">https:\/\/github.com\/MightyDevices\/docker-gcc-arm-none-eabi-builder<\/a> <\/p>\n\n\n\n<h2>Step 2: We need something for debugging and uploading the firmware &#8211; OpenOCD. <\/h2>\n\n\n\n<p>Sadly enough If you, (like me) use Windows as your Host OS this step cannot be done in a Docker as Docker Desktop on Windows has no capability to forward the host&#8217;s USB to the containers so it can&#8217;t use the programming adapters like (STLink or any of the FTDI based JTAGs\/SWDs). We need to install the OpenOCD within the Host OS.<\/p>\n\n\n\n<p>Go to the <a href=\"https:\/\/github.com\/gnu-mcu-eclipse\/openocd\/releases\">https:\/\/github.com\/gnu-mcu-eclipse\/openocd\/releases<\/a> and look for a release that&#8217;s applicable for you operating system (I chose <a href=\"https:\/\/github.com\/gnu-mcu-eclipse\/openocd\/releases\/download\/v0.10.0-12-20190422\/gnu-mcu-eclipse-openocd-0.10.0-12-20190422-2015-win64.zip\">this<\/a>). Next, extract the zip contents to the directory of your choosing. The main executable is in the directory <code>bin<\/code>. Add this directory to the system <code>PATH<\/code> so that the <code>openocd<\/code> is accessible from command line in any directory.<\/p>\n\n\n\n<p>Since this tutorial uses the STM32L433 as an example we may as well do a quick check whether the OpenOCD works. Find yourself a Nucleo board with any MCU from the STM32L4 familiy and type the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openocd -f board\/st_nucleo_l4.cfg<\/code><\/pre>\n\n\n\n<p>If the OpenOCD did not exit and your output looks something like this then you are good to go:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GNU MCU Eclipse OpenOCD, 64-bitOpen On-Chip Debugger 0.10.0+dev-00593-g23ad80df4 (2019-04-22-20:25)\nLicensed under GNU GPL v2\nFor bug reports, read\n        http:\/\/openocd.org\/doc\/doxygen\/bugs.html\nInfo : The selected transport took over low-level target control. The results might differ compared to plain JTAG\/SWD\nadapter speed: 500 kHz\nadapter_nsrst_delay: 100\nnone separate\nsrst_only separate srst_nogate srst_open_drain connect_deassert_srst\nInfo : Listening on port 6666 for tcl connections\nInfo : Listening on port 4444 for telnet connections\nInfo : clock speed 500 kHz\nInfo : STLINK V2J33M25 (API v2) VID:PID 0483:374B\nInfo : Target voltage: 3.244649\nInfo : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints\nInfo : Listening on port 3333 for gdb connections<\/code><\/pre>\n\n\n\n<p>OpenOCD does not limit you to the STM32L4 family: if you are planning a project using other micro then take a peek under the <code>scripts\/boards<\/code> directory and choose a script that suits you the most.<\/p>\n\n\n\n<h2>Step 3: Test connection between the OpenOCD and the GDB running inside a Docker container<\/h2>\n\n\n\n<p>This is just a test to tell whether the networking between the Docker containers ad you Host OS is working as expected. From the OpenOCD&#8217;s output provided above you can tell that the OpenOCD expects a connection from GDB on port 3333. That&#8217;s the default configuration and I&#8217;ll stick to it for the rest of this article.<\/p>\n\n\n\n<p>Let&#8217;s begin with a fresh start of the OpenOCD, just like we did before (make sure that the target board you wish to develop on is connected!): <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openocd -f board\/st_nucleo_l4.cfg<\/code><\/pre>\n\n\n\n<p>Follow that by starting the container using the following command. You should be left with container&#8217;s shell:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run --rm --name test -it twatorowski\/gcc-arm-none-eabi bash<\/code><\/pre>\n\n\n\n<p>Now let&#8217;s try to connect the GDB with the OpenOCD. In the shell start the <code>gdb<\/code> process:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>arm-none-eabi-gdb<\/code><\/pre>\n\n\n\n<p>Then within the running GDB type the following command that will establish the connection to the <code>gdb-server<\/code> part of the OpenOCD:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>target remote host.docker.internal:3333<\/code><\/pre>\n\n\n\n<p>The address <code>host.docker.internal<\/code> points to your Host OS. If the output from all above looks something like this then <strong>everything is fine<\/strong>!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>c:\\>docker run --rm --name test -it gcc-arm-none-eabi sh\n\/ # arm-none-eabi-gdb\nGNU gdb (GDB) 8.3\nCopyright (C) 2019 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\nType \"show copying\" and \"show warranty\" for details.\nThis GDB was configured as \"--host=x86_64-pc-linux-musl --target=arm-none-eabi\".\nType \"show configuration\" for configuration details.\nFor bug reporting instructions, please see:\n&lt;http:\/\/www.gnu.org\/software\/gdb\/bugs\/>.\nFind the GDB manual and other documentation resources online at:\n    &lt;http:\/\/www.gnu.org\/software\/gdb\/documentation\/>.\n\nFor help, type \"help\".\nType \"apropos word\" to search for commands related to \"word\".\n(gdb) target remote host.docker.internal:3333\nRemote debugging using host.docker.internal:3333\nwarning: No executable has been specified and target does not support\ndetermining executable automatically.  Try using the \"file\" command.\n0x08006c40 in ?? ()\n(gdb)  <\/code><\/pre>\n\n\n\n<p>You can test some basic commands here. For example, let&#8217;s try to crank up the Nucleo SWD interface clock speed to it&#8217;s maximum using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) monitor adapter_khz 4000\nadapter speed: 4000 kHz<\/code><\/pre>\n\n\n\n<h2>Step 4: Get the IDE &#8211; VSCode<\/h2>\n\n\n\n<p>This is as simple as obtaining installing the Visual Studio Code from here: <a href=\"https:\/\/code.visualstudio.com\/ \">https:\/\/code.visualstudio.com\/<\/a>. Start the VSCode editor.<\/p>\n\n\n\n<p>It is worth to install couple of plugins that make the development process pleasant. Here&#8217;s my list in the alphabetical order:<\/p>\n\n\n\n<ul><li><strong>C\/C++ <\/strong>&#8211; syntax highlighting and debugging capabilities.<\/li><li><strong>Code Spell Checker<\/strong> &#8211; helps to avoid spelling mistakes in code and comments.<\/li><li><strong>Cortex-Debug<\/strong> &#8211;  ARM Cortex-M GDB Debugger support for VSCode, can display Peripherals, Core registers, Function Disassembly, Memory View and so on, BUT useful only when you have the <code>arm-none-eabi-gdb<\/code> installed in your host OS. <em>Sadly enough does not support the gdb pipe launch which means that it cannot communicate with the gdb residing in Docker container<\/em>.<\/li><li><strong>Doxygen Documentation Generator<\/strong> &#8211; helps to create Doxygen headers for new files, functions, etc&#8230;<\/li><li><strong>Head-File-Guard<\/strong> &#8211; Generator of the infamous <code>#ifndef ...<\/code> <code>#define ...<\/code> <code>#endif<\/code> header file guard<\/li><li><strong>Linker Script<\/strong> &#8211; Language support (syntax coloring) for the linker scripts<\/li><li><strong>TODO Highlight<\/strong> &#8211; Highlights comments that contain words like <code>TODO:<\/code> or <code>FIXME:<\/code>, can generate a list of TODOs and FIXMEs.<\/li><\/ul>\n\n\n\n<h2>Step 5: Prepare a project within the VSCode that uses all we did above<\/h2>\n\n\n\n<p>Start by downloading the source code that you want to build. Let&#8217;s proceed with the STM32L433 startup project. Then go to it&#8217;s main directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/MightyDevices\/startup-stm32l433\ncd startup-stm32l433<\/code><\/pre>\n\n\n\n<p>NOTE: Make sure that your project directory has no whitespace characters.<\/p>\n\n\n\n<p>VSCode uses <code>.vscode<\/code>  folder  inside the main project directory to store all tasks (like Build, Clean) and launch configurations (like Debug). I&#8217;ve prepared all the files needed so let&#8217;s start with a clean directory and get these:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/MightyDevices\/vscode-project-settings-docker-arm-none-eabi-gcc .vscode<\/code><\/pre>\n\n\n\n<p>Now we are officially ready to start coding in VSCode. Start the VSCode in the project directory. After the VSCode has launched. If you press <code>shift+ctrl+b<\/code> you&#8217;ll see the picker with four options. Two of these must be invoked before anything gets uploaded (but only once in a life cycle of the VSCode) into the target device: <code>Start OpenOCD<\/code> and <code>Start Docker<\/code>.<\/p>\n\n\n\n<p>In order to have the includes from the docker&#8217;s arm-none-eabi-gcc toolchain within the reach of VSCode a special task was prepared: <code>Copy Includes<\/code> This is to be executed only once per project and will extract all the <code>*.h<\/code> files to the project&#8217;s <code>.includes<\/code> directory. For the sake of Intellisense <code>settings.json<\/code> file was prepared so that files from the <code>.includes<\/code> can be resolved within the project.<\/p>\n\n\n\n<p>After that whenever you&#8217;ll press F5 the firmware will get build, uploaded and the execution will start. Don&#8217;t forget to add breakpoints to see the debugging in action \ud83d\ude42<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" width=\"1976\" height=\"1400\" src=\"https:\/\/mightydevices.com\/wp-content\/uploads\/2019\/09\/debug.gif\" alt=\"\" class=\"wp-image-1037\"\/><\/figure>\n\n\n\n<p>If you want to change the name of the output <code>*.elf<\/code> file then don&#8217;t forget to update your <code>.vscode\/launch.json<\/code> as well.<\/p>\n\n\n\n<p>Happy debugging!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial I&#8217;ll shortly describe how I setup my development environment for the STM32 micros. STM32L433 will be used as an example but the following process shall be applicable to any other STM32 micro. Step 1: Get the Toolchain In order to make the whole development process portable (i.e. to allow other parties to&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[13,5,12],"_links":{"self":[{"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/posts\/1018"}],"collection":[{"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/comments?post=1018"}],"version-history":[{"count":22,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/posts\/1018\/revisions"}],"predecessor-version":[{"id":1057,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/posts\/1018\/revisions\/1057"}],"wp:attachment":[{"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/media?parent=1018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/categories?post=1018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mightydevices.com\/index.php\/wp-json\/wp\/v2\/tags?post=1018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}