Keil and STM32 Programming — Fixing issues in CMSIS Libraries

Sanskar Biswal
TheTeamMavericks
Published in
5 min readMay 29, 2020

STMicroelectronics has its own suite of development tools like STMCube IDE and STMCubeMX. While CubeMX is a great tool for avoiding the fine details like register level initialization of clock and system peripherals, Keil provides several builtin tools like CMSIS Libraries. CubeMX has the option of including the CMSIS libraries, however, they appear to be out-dated or incomplete. Thus, several features end up missing in the final build file. Additionally, Keil is a familiar interface and development tool for several Embedded System developers, so it makes no sense to switch to a new IDE for only a single platform.

What is CMSIS and Why is it a big deal?

Fig. 1 CMSIS Architecture

Cortex Microcontroller Software Interface Standard (CMSIS), is a library of compiled and executable code which can drastically improve the overall performance of ARM devices. The most popular among these are CMSIS-NN and CMSIS-DSP.

These libraries are used for optimized performance in Neural Network and Digital Signal Processing operations. CMSIS-DSP has functions for average, standard deviation, mean, distance functions and SVM classification. Not only does this help reduce development time, the operations run upto 10–30 times faster when using CMSIS libraries.

Thus, it is understandably a problem if some features live SVM functions are not initialized when initializing a project from CubeMX. Thus, in the following section I will be providing a detailed approach to avoid this problem while still making use of the code generation ability of CubeMX.

Creating a New Project

Traditionally, creating a project would be done directly using CubeMX, but in this case, we will create an empty project in Keil and then use CubeMX to generate the files within.

Fig.2 Create A New Project in Keil

Select create a folder for your project and save the project name. In my case, I am calling it init.

Fig.3 Select Target Device

STEP.1 The project creation wizard will now ask you to select your target device. In my case, I am using an STM32F4 Discovery board. The target device is thus, STM32F407VGtx. Press OK to go to the next step.

Fig.4 Manage Runtime Environment

STEP.2 In the next step, the Manage Runtime wizard shows up. We need to add the CMSIS files and libraries in this step.

  • Under Build Target, select STM32F4-Discovery.
  • Open the CMSIS options and select CORE, DSP and NN. I prefer to set the DSP option to Library, but you can let it remain at Source. This will however lead to bigger build size, so you will have to select based on your requirements.
Fig.5 Initializing Device with CubeMX

STEP.3 Under the Device Options -> STM32Cube Framework, select the option of STM32CubeMX.

You will see a small play button next to it. Clicking that will launch CubeMX software and we can declare the pin config as usual.

In this project, I will not be initializing any peripheral but you can do any peripheral init like SPI or UART just as easily. Only the user button (PA0) and the LED’s on the board (PD12 - PD15)

Fig.6 Button and Pin Setup in STM32CubeMX
Fig.7 Close CubeMX

Pressing the GENERATE CODE button will initialize the project in your existing project where you called the CubeMX. Press the CLOSE button and exit from CubeMX to return the the Keil Project. The Manage Runtime Environment wizard should still be open. Ensure the CMSIS selections are still intact and then press the Resolve button on the bottom left. This will correct any errors if there are any. If everything is fine, then press OK to generate the project. Since the project is being generated in Keil, thus any CMSIS library dependency will be generated correctly. CubeMX is only used for pin and peripheral initialization.

Fig.8 Final Environment Configuration
Fig.9 The Project Structure

As you will see in the new project structure, CubeMX code is now under a separate folder group. The main.c file in it can now be used normally, without the worry of missing dependencies.

If you need to make changes to the existing pin configuration, then open the run-time management option and click the Play button next to CubeMX. Make changes and click GENERATE CODE. Resolve and return to your project. It is that simple.

Note: Each time you use generate code in CubeMX, the existing code in while loop in the main function is erased. Thus, make sure to make a copy of the code, if any exists in the while loop.

Conclusion

The aim of this guide was to resolve several issues when developing with CMSIS libraries. Not only will this method fix any errors from incorrect and potentially non-existing header definitions, it will also make it easier to work with CubeMX and CMSIS in a project.

In retrospect, I would suggest using this method even if you are not using DSP or NN libraries as initializing a project this way gives you the full benefits of CubeMX while ensuring that there are no build/project errors within Keil. This makes it much more easy to update projects where the peripherals are added later or there needs to be a change without compromising the usability of the project after an update.

--

--

Sanskar Biswal
TheTeamMavericks

Electronics Engineer | Firmware Developer | Programmer | Poet | Writer