2
votes

I am working with STM32F103C8T6 and would like to use CMSIS, which is essentially just register definitions and no code, to make my life easier while still staying at a low level. The problem is that I have no idea how to install the library for use on the command line with Makefile. All documentation seems to be bound with a vendor-specific IDE like STM32CubeIDE.

I suppose the first thing to do is to download the CMSIS library, which I found on GitHub. However, after unzipping ARM.CMSIS.5.6.0.pack I found no files named stm32f10x.h. I spend some more time and found a CMSIS pack for the specific MCU I'm using, but it doesn't contain core_cm3.h, which however presents in ARM.CMSIS.5.6.0.pack. The document says I need to include both to my project, so do I need to copy the files downloaded from different places to my project, or what?

As a bonus question: what is the relationship between CMSIS and Keli? The device-specific CMSIS pack is downloaded from www.keil.com, but I don't want to use Keil MDK for now, as it appears to be a commercial product, and the GNU Arm toolchain is serving me pretty well.


Edit: I should have been more specific from the beginning, but now let's focus on how to build the Basic CMSIS Example as a minimal, complete and verifiable example.

What I have done:

  1. Download and unzip CMSIS-Core and CMSIS-DFP to /Users/nalzok/Developer/CMSIS/ARM.CMSIS.5.6.0/ and /Users/nalzok/Developer/CMSIS/Packs/Keil.STM32F1xx_DFP.2.3.0/, respectively.
  2. Create a file named main.c, and copy the content of the basic example to it.
  3. Add #define STM32F10X_MD on the very first line to specify the chip.
  4. Fix typos: replace the : on line 31 to ;, and replace line 33 to timer1_init (42);.
  5. Build and get an error

/tmp $ arm-none-eabi-gcc -I/Users/nalzok/Developer/CMSIS/ARM.CMSIS.5.6.0/CMSIS/Include/ -I/Users/nalzok/Developer/CMSIS/Packs/Keil.STM32F1xx_DFP.2.3.0/Device/Include/ main.c
main.c: In function 'main':
main.c:42:5: warning: implicit declaration of function 'Get_InputValues' [-Wimplicit-function-declaration]
   42 |     Get_InputValues ();                          // Read Values
      |     ^~~~~~~~~~~~~~~
main.c:44:5: warning: implicit declaration of function 'Calculation_Response' [-Wimplicit-function-declaration]
   44 |     Calculation_Response ();                     // Calculate Results
      |     ^~~~~~~~~~~~~~~~~~~~
main.c:45:5: warning: implicit declaration of function 'Output_Response' [-Wimplicit-function-declaration]
   45 |     Output_Response ();                          // Output Results
      |     ^~~~~~~~~~~~~~~
/var/folders/m4/7my6q_kj6pxgzb1b7pxyhp0h0000gn/T//cc1ZVBaH.s: Assembler messages:
/var/folders/m4/7my6q_kj6pxgzb1b7pxyhp0h0000gn/T//cc1ZVBaH.s:197: Error: selected processor does not support `wfe' in ARM mode
/var/folders/m4/7my6q_kj6pxgzb1b7pxyhp0h0000gn/T//cc1ZVBaH.s:310: Error: selected processor does not support `cpsid i' in ARM mode
/var/folders/m4/7my6q_kj6pxgzb1b7pxyhp0h0000gn/T//cc1ZVBaH.s:318: Error: selected processor does not support `cpsie i' in ARM mode

As per @KamilCuk's comment below, I added more options and commented out the functions Get_InputValues, Calculation_Response, and Output_Response, but now I am having some different errors.

/tmp $ arm-none-eabi-gcc -I/Users/nalzok/Developer/CMSIS/ARM.CMSIS.5.6.0/CMSIS/Include/ -I/Users/nalzok/Developer/CMSIS/Packs/Keil.STM32F1xx_DFP.2.3.0/Device/Include/ -D STM32F1 -D STM32F103x6 -mthumb -mcpu=cortex-m3 main.c
/Users/nalzok/opt/xPacks/arm-none-eabi-gcc/9.2.1-1.1/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: /Users/nalzok/opt/xPacks/arm-none-eabi-gcc/9.2.1-1.1/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp/libc.a(lib_a-exit.o): in function `exit':
exit.c:(.text.exit+0x16): undefined reference to `_exit'
/Users/nalzok/opt/xPacks/arm-none-eabi-gcc/9.2.1-1.1/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: /var/folders/m4/7my6q_kj6pxgzb1b7pxyhp0h0000gn/T//ccqfC5LA.o: in function `Device_Initialization':
main.c:(.text+0x164): undefined reference to `SystemCoreClock'
collect2: error: ld returned 1 exit status
2
The source is on github. Ex. CMSIS_5. how to install the library for use on the command line with Makefile - you don't "install", you compile from sources and add include paths to your compiler, there is no installation.KamilCuk
So basically, building something specific to e.g. STM32 requires -I to the path of CMSIS-Core and the corresponding STM32 DFP, whereas developing for generic Arm Processors only calls for -I to the former? The examples unfortunately doesn't specify the compiler options to build it.nalzok
The compiler options are specific to compiler, not to the library you use. I really don't understand what exactly you ask about. Like with any other library you would add to your project from the source code, link with object files compiled from the library and add include paths. You ask about makefile, so I assume you are aware how to do those things (are you?). I recommend using cmake for easier scripting and managing. The examples show how to use the library, not how to compile with it. With recent STM32CubeMX you can generate makefiles, if you want.KamilCuk
relationship between CMSIS and Keli? - CMSIS is a library designed by ARM (the company "Arm Holdings"). Keil is a company that was acquired by ARM in 2005 and still exists and still offers producets. One is a library, the other is a company. Keil MDK, a product made by the company Keil, uses CMSIS as a library.KamilCuk
And you need the linker file and startup script, otherwise wrong memory regions will be flashed and interrupts vectors will not be handled.KamilCuk

2 Answers

3
votes

For the latest device headers, I suggest downloading STM32CubeF1 package from the ST website. Among other things (Middlewares, HAL etc.), this package contains the required device headers in /Drivers/CMSIS/Device folder. You need STM32F103xB symbol defined for stm32f1xx.h header to work correctly.

Of course, STM32CubeF1 package also contains CMSIS libraries but they are generally a little bit outdated. I prefer to download them as .pack files from the github repo you mentioned. You need the headers in /CMSIS/Core at least. You may add additional parts of the CMSIS if you wish. Some of them (like DSP) may also need you to add static libraries provided in /Lib folders.

Please be aware that if you clone the CMSIS repo from github instead of downloading the .pack file, you end up with placeholder versions of the static libraries, as the project uses git LFS. You can't use these static library files (.a files) directly as they are just some kind of pointers. I'm not familiar with git LFS, but I guess you need some git commands (maybe checkout) to tell your PC to download the actual .a files.

Also note that sometimes CMSIS folder structure changes from version to version. The folder structure you get in STM32CubeF1 may be different from the one you download from the official CMSIS repo.

I forgot to mention: Other than CMSIS and ST device headers, you also need the following files:

  • system_stm32f1xx.c (STM32CubeF1 package /Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates folder)
  • startup_stm32f103xb.s (STM32CubeF1 package /Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc folder)
  • A linker script from STM32CubeF1 package /Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/linker folder. Strangely, there is none for STM32F103x8, so you probably need to pick STM32F103xB and modify it. I use an IDE generated one.

Update:

Here you can find a minimal project created in STM32CubeIDE. I created an empty C project. The IDE provides a linker script and a startup file (.s) but I deleted them and used the ones included in the STM32CubeF1 package. I also deleted unrelated header files from the /Drivers/Device/ST/STM32F1xx/Include directory. But I didn't touched the ones in the /Drivers/CMSIS/Core/Include although there are lots of unrelated files there, as it's harder to determine which ones are needed and which ones are not.

I know that you look for a solution without an IDE, but I think this example project can at least give you some clues about the required files and the project structure.

Note: The example project name is blinky.cube but there is no Cube in the project. I use this naming convention just to specify the IDE I use, which is STM32CubeIDE in this case.

3
votes

For the part of CMSIS your are referring to, some is supplied by ARM (CMSIS core) and some is supplied by your chip vendor (Device Family Pack). As you have discovered, CMSIS software packs are just zip files by another name. You may unzip them wherever you wish. As you are aware, core CMSIS and most of the vendor specific part consists of just header files. It is then necessary to include the proper directories in the compiler include path, typically using -I... command line options.

One type of vendor software pack is called a Device Family Pack. In addition to vendor specific peripheral definitions, they usually contain start up code and often times linker scripts that match the layout of the SOC memory. These are worth finding and will save the work of vector table layout and other such low level code.

For the bonus: Keil is a maker of software tools and is owned by ARM. The nicer features of CMSIS software packs, like distributing and updating them over a network, are supported by the Keil IDE and Keil maintains a repository of common SOC packs. I also usually use the GNU compiler, but have used Keil and its built-in CMSIS awareness and software pack availablity to good effect. I have even built a few software packs for custom work. I suggest a continued reading of the CMSIS documentation paying some attention to the section on packs. You don't have to have an IDE that manages the packs for you. Since they are simply zip files, you undertake that task yourself.