CLion for Embedded Development Part II

Hi,

This is a second guest blog post by Ilya Motornyy about programming for microcontrollers in CLion.

Upd. An alternative approach from Klaus Nagel in a small demo project on GitHub: Embedded Development on STM32 with CLion and the Segger Tools.

Ilya Motornyy
Ilya Motornyy

Java/JavaScript Developer at Vaadin.com
DIY Electronics and Embedded Programming Enthusiast

History

About one and a half years ago I wrote a blog post about using CLion for embedded software development. Long story short, I used an ST demo board (reflashed into SEGGER JLink-compatible probe), STM32CubeMX code generator, GCC ARM toolchain, and SEGGER Ozone on-chip debugger to run some demonstration project. That combo seems to be a working solution, but, on the other hand, there were some complications with the re-flashing probe, with running an external debugger (why would we run one if we already have awesome CLion?), also there were SEGGER license limitations, etc.

Of course, I wasn’t happy having all of those problems and tried to find better solutions. Now it’s time to show what I’ve managed to achieve. Fortunately, during this time, both CLion and CubeMX were improved a lot, made more stable, and, most importantly, CLion now supports remote GDB. Now it’s possible to use OpenOCD (Open On-Chip-Debugger) as a flash probe and as a remote gdb server. This unlocks the possibility to get rid of both SEGGER license limitations and using a commercial debugger in favor of open-source tools. Also, there is no need anymore to reflash any on-board probes, we can use it as-is, even for flashing your production target devices (refer to ST Nucleo or Discovery board user reference).

I managed to run this environment with vanilla CLion, but the project setup was quite complicated and time-consuming, and at some point, it turned into the idea to write my own plugin for CLion, which puts it all together. Now the plugin is in beta stage, published to the JetBrains plugin repository, and I am glad to show how it works. Today we will run a small demo project (It’s gonna be blinking LEDs! Surprise!) using one of the most popular boards – STM32F4-Discovery. The same example, with minimal changes, can be done using any of STM32 board of Nucleo, Discovery or EVAL series, since they all have LEDs onboard.

Required tools

CLion

First of all, you need the IDE itself. You can download it directly from the JetBrains site. Run the installer and follow the instructions. Also, you need a license. The one-month trial license is enough for the first try. To use a toolchain, you need MinGW or Cygwin on Windows, and binutils on Linux. The installation manual is here.

The plugin

Open the Settings dialog, go to the Plugins tab, click Browse Repositories… and find the plugin using the openocd keyword. Click the Install button and restart CLion after the installation.
embo_image7
Now CLion has an additional run configuration, two additional menu items in Tools, and one more in the Settings dialog tab.

Toolchain

A toolchain is a set of cross-platform tools to compile and link your program. Cross-platform here means you run them on your PC or Mac, but the result can be only run under the target environment, which is ARM MCU in our case.
There are a number of toolchains for ARM, for instance, Clang and GCC are free and both supported by CLion, and there are a number of other compilers (Keil, IAR, Raisonance, etc). I use GCC; you can download it from here. Note the toolchain must be in the system path after installation. You can check that by running arm-none-eabi-gcc from the command line.

OpenOCD

OpenOCD is an open source on-chip debugger, which supports a number of different hardware in-circuit debuggers and flashers, a huge number of different MCUs, flash chips, etc. So, potentially you can use this guide to develop firmware for a huge number of hardware configurations, not limited to ST products.
There are three key features to be used:

  • ST-Link/V2 in-circuit debugger support
  • ARM Cortex M series MCU support
  • Remote GDB protocol support

OpenOCD is distributed primarily in source form, but there are a couple of unofficial binary distributions. You can find them at http://openocd.org/getting-openocd/. If you use Windows, you also need the ST-LINK/V2 driver installed. The driver is usually shipped with the OpenOCD binary distribution for Windows, but you can download the latest version of the driver together with a rather handy flashing utility from http://www.st.com/en/development-tools/stsw-link004.html.

STM32CubeMX

STM32CubeMX is a free initialization code generator, in which you can define the configuration of both CPU and peripheral devices of our MCU. All that is done with a pretty handy visual interface, you can adjust all the frequencies, pin modes, peripherals. Then the Cube generates the stub of your project, i.e. a bunch of .c and .h files together with specific project files for the supported IDEs (unfortunately, CLion is not one of those IDEs). Cube software contains the program itself and many automatically downloaded “Firmware Packages”, each of which is specific to a certain MCU family. You can download the tool here.

Let’s do an example

For the example, I chose a very popular board – STM32F4-Discovery. It has a powerful MCU STM32F407 on board, an ST-LINK/V2 compatible flash probe, and four user LEDs. There is also a microphone, a sound output, an accelerometer, and a USB interface, but let’s not get ahead of ourselves – the example is going to control only LEDs. If you already have any other STM32-based board, such as Discovery, Eval, or Nucleo series, you can implement the same example with several minimal and quite obvious changes – all of those boards have at least one user LED.

Configure the board

OK, now that we have all the tools installed, let’s try to make “advanced blinky” example from out of our STM32F4-Discovery. First of all, we need to run CubeMX. It will download an actual list of available MCU and demo boards from somewhere, and when it’s done you may choose any of STM32 MCUs, but we are more interested in boards. You can find them on the “Board Selector” tab. Just choose STM32F4DISCOVERY and double-click it.
embo_image13

Now you can configure pin modes, peripherals, and clockings in three of the four tabs, and calculate the estimated energy consumption with the “Power Consumption Calculator” tab.
embo_image14

For our very first project, we have all the LED pins already configured as GPIO outputs (we started with the board, but not with a chip alone, if you remember), and those pins have their own names LD3…LD6.
The next step is in the Cube project settings and code generation – you need to choose a base project folder, a project name, and then set Toolchain/IDE to SW4STM32.
embo_image12

Now you can close the dialog and press the gear-looking button. Then close the final dialog. If you need to change your hardware configuration later, just reopen the chip config, make changes, and then regenerate the code.

The next step is to open the project with CLion. Use File -> Import from the main menu, or Import Project from Sources from the Welcome screen. Most probably CLion will ask something and report errors – just ignore that. When the project is open, click Tools->Update CMake project with STM32CubeMX project.
embo_image8

The plugin rewrites the CMakeLists.txt file completely, and, thus, the toolchain is taken into use, and now you can compile the stub of the project. Also, the plugin creates a new run configuration to download the firmware to the chip and debug it.

Setting the plugin parameters

Open the Settings dialog and find the plugin under the Build, Execution, Deployment group.
embo_image11

You need to set the OpenOCD location, the plugin tries to find the locations automatically with the system path, but you may provide an explicit one. Most probably, you do not need to touch the ports settings and the gdb location (CLion bundles GDB with the multi-arch support on Windows and Linux, on macOS you have to use custom GDB build).
The very last thing to do is set the board configuration file. Those files are located in the boards folder in OpenOCD distribution. For our project, stm32f4discovery.cfg is obviously the best option. You can use the Choose file dialog to select the file.

Writing the Example

Now we have everything set up and ready, let’s just write some code. Open main.c and add some example code into an endless while loop, see lines 106-111 below:
embo_image6

This code just switches on and off the onboard LEDs randomly every 300 ms.
Also, you can add several #pragma directives (lines 100, 101, and 113) to get rid of CLion warnings – endless loops are not used in “normal” C programs, and the IDE reports that.

Running the example

Now it’s time to set a breakpoint somewhere in the code and run the firmware! CLion will compile the code, then download it to the MCU, then connect the debugger and reset the chip.
Now you can use breakpoints and watch expressions. This video shows how it works:

Further Development

Now you have a small example up and running, but how should development be done? Ok, here are some Qs and As.

Q: Which kind of boards are supported?
A: Basically any of STMicroelectronics boards of series STM32 Discovery, Nucleo, or EVAL should work.

Q: How can I change my MCU hardware configuration?
A: Just run STM32CubeMX again, reopen your project, and then rerun the code generation. The plugin will ask you if the whole project should be updated according to your changes. Just say “Yes”.

Q: How can I preserve my code during the code regeneration?
A: Always put your code between comments of type
/* USER CODE BEGIN ??? */
and
/* USER CODE END ??? */.
Cube does not touch those parts of the source code. Do not forget to move CLion’s automatically generated includes into an appropriate unchangeable block. Another option, for big chunks of code, would be to use separate .c/.h files.

Q: I need to include a library in the project, enable FPU, or make some other change to CMakeLists.txt. How do I do that?
A: CMakeLists.txt is always regenerated from a template during project update, and all the changes to it will be lost. The template itself is put into the project folder and named CMakeLists_template.txt. Please change the template and then update the project using Tools->Update CMake project with STM32CubeMX project menu item.

Q: I want to use CLion for my ARM development, but I do not use stm32. Can I use the plugin?
A: Most probably, you can. You need to install the same tools except for Cube, and then make your own CMakeLists.txt (you may use this template), a linker script, and a board configuration file. When you have them, click Tools -> CMake -> Reset Cache and Reload Project and then create your own run configuration of type OpenOCD Download & Run. One of the plugin users reported he managed to run his Atmel SAM E70-based project with the plugin.

Q: I want to use CLion for my development, but I do not use ARM chips. Can I use the plugin?
A: Well, if you have any MCU and a flash probe supported by OpenOCD and GCC, you can at least try. Install a suitable toolchain, and see the answer above.

Q: I can not use any of the existing board configuration files. Can I use separate config files for the interface and for the target?
A: You can combine those into one file and use it. Any of existing board configurations is the example.

Q: I love all this stuff, can I support your work?
A: Sure!

References

This entry was posted in Tips'n'Tricks and tagged , . Bookmark the permalink.

52 Responses to CLion for Embedded Development Part II

  1. Oleksii Vynnychenko says:

    Oh, wow, will definitely look at that for my hobby. Thank you a lot! :)

  2. Mario says:

    Evaluate that option, but gave up because CLion does not support core dump debugging. On embedded system it’s not always possible to run a remote debug session

  3. Konstantin Volodin says:

    Is it for Windows only?

  4. mintisna says:

    When I set OpenOCD Home path, it shows invalid error as below:
    https://github.com/elmot/f4-blog/issues/2

  5. mintisan says:

    Must I install CLion with Cmake and Mingw/Cygwin?

  6. Max says:

    I tried CLion 2017.3 and 1.0.beta1 version of plugin under Win7, but couldn’t set up openocd’s home in Build, Exec, Deploy section of settings.
    I dl’ed OpenOCD v0.10.0 binary packages for windows, extracted them under d:/openocd (so that binary is d:/openocd/bin/openocd.exe). Then i tried to specify this path in OpenOCD Home input, but it keeps failing, saying ‘Cannot save settings: OpenOCD Home is invalid’. I tried Freddie Chopin’s and Liviu Ionescu’s binary packages, but both failed with same result. Neither d:/openocd, nor d:/openocd/bin had success. Changing slashes to backslashes didn’t play too.
    As a side note, i dont have openocd’s binary in PATH env, but i have working openocd installation, which is used with Eclipse. That openocd didnt fit for your plugin too.
    How cn i fix it? Would be glad if you provide any tip or solution. But thanks for your effort anyway!

  7. Klaus Nagel says:

    Great Work!
    Since every new STM Demo- Board now can be changed to behave like a Segger J-Link (https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/) I don’t need the OpenOCD integration but the plugin will it make much easier to get an initial project up and running.

    I set up a small demo project using the CLion provided launch configuration for gdbserver together with the J-Link gdbserver.
    If you are interested, i can post a short tutorial on how to do it.

    • Anastasia Kazakova says:

      Sure, will be glad to learn more.

    • elmot says:

      Actually I have tried this approach about year ago. That time segger’s gdbserver did not work normally with CLion. Good to know it works now.
      If you read my first blog post here (https://blog.jetbrains.com/clion/2016/06/clion-for-embedded-development/), you can find, we already used reflash to segger.

      • Klaus Nagel says:

        I put my approach in a small demo project on github: https://github.com/nagelkl/clion_embedded. I suspect the CLion gdbserver configuration expects a running gdbserver with a loaded executeable on the target like a remote linux machine. It took me a wihle to figure out the workaround with the gdb hooks in .gdbinit to force a download of the executeable via the JLink

        • Anastasia Kazakova says:

          Thanks, Klaus. Yes, seems you are right.

          • Klaus Nagel says:

            By playing around wiht my demo i realized that the .gdbinit in my project- root gets not loaded. Instead there is the .gdbinit in my Home- Directory, which gets loaded. Unfortunately there was one there from my experimets so i didn’t notice that in the first place. Does CLion load the gdb ececuteable via an absolute path, so that the .gdbinit in the project root is not loaded? For a qick fix i copy my .gdbinit via a batch file to the right place, but for the next project this might be easily overlooked.

          • Anastasia Kazakova says:

            Yes, currently the one from the Home directory is used. We plan to add an ability to load .gdbinit from the project root, but it’s not yet there.

  8. Kiilii says:

    Thanks for If I need to switch between projects using stm32f1xx and stm32f4xx, do I have to change plugin settings for different board configure files every time?

  9. Kiilii says:

    Another question:
    I used CubeMx to generate a SW4STM32 project, path like this: “D:\Projects\testprj1\sw4stm32\.cproject” , and all “Drivers/Inc/Src” folders are at the same level with “SW4STM32” folder. So I used Clion to import the “D:\Projects\testprj1” folder. But when I use “Tools->Update CMake ….” , the plugin says “file .cproject is not found in the project directory D:/Projects/testprj1”. What should I do?
    All related softwares are the newest version.

  10. Sergey says:

    I have created a clean project and it was compiling fine. But then I have added my files, and now I see a strange link error:

    /usr/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m/libm.a(lib_a-w_hypot.o): In function hypot':
    w_hypot.c:(.text.hypot+0x8e): undefined reference to
    __errno’
    w_hypot.c:(.text.hypot+0x98): undefined reference to `__errno’

    What might be wrong?

  11. radex says:

    Just asking… Does this support multithreading? I know that this meight be a stupid question, but i am just asking….

  12. YKolokoltsev says:

    Thank you very much! This is just a WOW solution, I was waiting for something like this for a half of a year for my new Nucleo-144 with STM32F746. I’m an Ubuntu user, with a 16.04 version and the latest 2017.3.3 CLion.

    You part worked with my Nucleo board just as you wrote, but the OpenOCD required a little configuration. Any interested can see my installation guide below:

    ****
    Because of absence of my board in the 0.9.9 I had to compile the latest OpenOCD 0.10.0 from github where the board/st_nucleo_f7.cfg is present following the next steps:

    git clone https://github.com/ntfreak/openocd.git
    cd openocd
    ./bootstrap
    ./configure –prefix=/home//Opt/OpenOcd –enable-stlink
    make
    make install
    sudo vim /etc/udev/rules.d/60-openocd-custom.rules

    # and copy there:
    ACTION!=”add|change”, GOTO=”openocd_rules_end”
    SUBSYSTEM!=”usb|tty|hidraw”, GOTO=”openocd_rules_end”
    ATTRS{idVendor}==”0483″, ATTRS{idProduct}==”374b”, MODE=”664″, GROUP=”plugdev”
    LABEL=”openocd_rules_end”

    In the case of any problems the reader can check out also this resource:
    https://github.com/TauLabs/TauLabs/issues/935

  13. Michael Niedermayr says:

    I followed the instructions and created a new clion project based on the STM32CubeMx Files using this plugin. Everything works fine and I can flash the stm32f4 discovery board. However, I can’t create c++ classes any longer. The class keyword is not recognized. Is this normal?

    • Anastasia Kazakova says:

      What do you mean not recognized? Where? Could you please share some sample?

      • Michael Niedermayr says:

        When I run this plugin to update the cmake, I cannot create c++ classes any longer. For example, if I right-click in the project window and select ‘C++ class’ in order to create a new c++ class, the ‘New C++ Class’ dialog opens. However, the ‘type’-dropdown list is empty. The ‘.cpp / .h’ type is missing.
        Now I am wondering if it should be this way and c++ is not supported or is there something wrong with my clion?

        • Anastasia Kazakova says:

          Could you please check if you have the corresponding file types configured under Settings/Preferences | Editor | Code Style | C/C++ | New File Extensions?

          • Michael Niedermayr says:

            Thx for your help Anastasia. Yes, the types are configured in the proper way.

            I just figured out that in the CmakeLists the compiler for the project is set to C (PROJECT(projectname C ASM) ). In order to use C++, you have to change this to PROJECT(projectname CXX ASM) and rename all generated .c files to .cpp (check the folders Src and Drivers/STM32F4xx_HAL_Driver/Src).
            The renaming only works for the Hal Libraries but not for the usb libraries in the Middlewares folder. But you can disable them in STM32CubeMX if you do not need them.

          • Anastasia Kazakova says:

            Ah, I see. Yes, CMake selected language affects the generation.

    • Michael Niedermayr says:

      I just wrote a short guide how to use this plugin with C++ and external programmers.
      You can find it here: https://github.com/zirrop/clion_stm32_openocd

  14. Łukasz Matuszewski says:

    Please add support for TCF (http://wiki.eclipse.org/TCF) to support http://www.lauterbach.com/frames.html?home.html (primary) and other
    embedded development tools.

  15. Nice information. i already installed in my pc cygwin terminal. but i don’t no how can configured toolchain platform with cygwin in case any stats?.

  16. Clark Sann says:

    Congratulations for making a wonderful plugin for CLion. I just got it up and running. I did have to fix a few setup errors before I could get it to work, but considering I’ve never used CLion nor your plugin before, I think you guys did a pretty good job to get a new guy up and running so quickly.

    I’ve been using SW4STM32. It’s OK I guess but I’m getting tired of the complexity of Eclipse. And I never could get Eclipse to debug a native MacOS C program using LLDB or GDB. And the Eclipse forum is worthless. So I started looking for an alternative and this morning I found CLion and your plugin. And now it’s all working. Cool!

    I’m going to buy CLion and contribute $$ to you for your efforts to make this plugin.

    Again, congratulations and thank you for your hard work!

  17. Xjeu Erydf says:

    What an excelent idea of converting a SW4STM32 project into a Clioen CMake project an daddign support for openOCD. +1 !!!

    I just installed the opeOCD plugin version 1.1 alpha . It converts the F4Disco demo project fine. The project builds w.o problem. I can flash the .bin or .hex using STM32 ST-link utility. All is fine i this department. The 4 LEDs flashes randomly as expected.

    There is NO way of telling the plugin and which board I’m using because some of the input fields in the openOCD support dialog is missing.
    Please refer to issue #128

  18. LongQing Zhao says:

    I tried to debug my board(stm32f103c8t6) like that you did,but it didn’t work.
    Also, I configed my target file to stm32f1x.cfg and used a usb line to connect my computer.
    The usb is a serial port use a chip call ch340g to change ttl.
    when I debuged with openocd, it always connected out of time, because of it unexpectedly used jtag.
    How can I do it let clion debug my stm32 successful?

Leave a Reply

Your email address will not be published. Required fields are marked *