📜 ⬆️ ⬇️

How we ran the standard examples from the STM32Cube library

Good day! It’s no secret that standard out-of-the-box examples are a good thing: uploaded to the board and enjoy. This is convenient for quick reference. But then, if we intend to create something ourselves, we need to parse the example code, read the documentation, write our code, debug it a long time ... I want to simplify this stage somehow. For this reason, I would like to talk about how we made the integration of standard examples from the STM32Cube library into Embox .

So, Embox, like any OS, provides a lot of nice things, such as threads, memory management, etc. The STM32Cube, in turn, has many examples of the use of hardware. Each example is a self-contained set of source codes with project files for MDK ARM, EWARM and SW4STM32 (something on top of Eclipse, it seems,), i.e. I pressed the button - everything was assembled by itself, the board was loaded and started. Now the question is: how to integrate such an example into the infrastructure of the operating system? Let's see in more detail how the examples are arranged.

For those who want to immediately look at what happened, and skip the technical details, jump here :)

I will draw on the example for the LCD screen and the BSP for the STM32F746G-Discovery debug board. Consider an example for the screen. In addition to the project files in the source tree are readme.txt, Inc / and Src /. We need them, go to the source folder and see what is there:
')
# ls Projects/STM32746G-Discovery/Examples/LTDC/LTDC_Display_1Layer/Src/ main.c stm32f7xx_hal_msp.c stm32f7xx_it.c system_stm32f7xx.c 

The system_stm32f7xx.c file is in all the examples, it contains the initialization of the built-in flash memory, the PLL, and also the SystemFrequency is installed. These functions are called before main (). In Embox, the same settings are made at system startup, so we simply will not use this file. We go further, in the file stm32f7xx_hal_msp.c contains hardware initialization functions that are specific to a particular task. These are functions of the form * _MspInit, which are initially defined as WEAK, which allows overriding them. We take this file with us in Embox. Further, stm32f7xx_it.c - here handlers of hardware interruptions and exceptions are redefined. And finally, main.c - everything is clear here - the basic logic + some initialization, which we then throw away.

The example is transferred to Embox using the import_stm32_cube_example.py script.
After its launch, the first thing is copied to the source tree readme.txt, Inc / and Src /. Now you need to generate the Embox build system file. For this purpose, a template is used in which the example name, source code, platform (f7 or f4) and necessary dependencies are substituted.

 /* GENERATED FILE */ package stm32_PLATFORM_.cmd @AutoCmd @Cmd(name="_EXAMPLE_", help="") @BuildDepends(third_party.bsp.stm_PLATFORM_cube.core) module _EXAMPLE_ { source "Src/embox_main.c" depends _EXAMPLE__Lib } @BuildDepends(third_party.bsp.stm_PLATFORM_cube.core) module _EXAMPLE__Lib { @Cflags("-Wno-unused") @IncludePath("$(ROOT_DIR)/platform/stm32_PLATFORM_/cmds/_EXAMPLE_/Inc") _SOURCES_ depends third_party.bsp.stm_PLATFORM_cube.stm32_PLATFORM__discovery_bsp depends third_party.bsp.stm_PLATFORM_cube.stm32_PLATFORM__discovery_components depends third_party.bsp.stm_PLATFORM_cube.stm32_PLATFORM__discovery_utilities } 

The third_party.bsp.stmf7cube.stm32f7_discovery_bsp and third_party.bsp.stmf7cube.stm32f7_discovery_components modules contain the CSP BSP library and various auxiliary libraries. Usually in the Cube project files these sources are explicitly listed, but in our system they are common and are connected in the same way for any example all at once. These libraries and all sources of the example will be compiled into some static library inside Embox (otherwise, the linking of the Embox commands with the weak Cube functions) is broken, therefore, to run the example, a file with the main () function will be generated.

With the build system sorted out, now you need to somehow remake the interrupt handlers from the Cube, so that the OS accepts them. The format of the interrupt handler in Cube is void (* handler) (void) , while in Embox the signature is different. Using the example of the DMA2_Stream7_IRQHandler handler in Embox, this can be done as follows:

 static irq_return_t embox_DMA2_Stream7_IRQHandler(unsigned int irq_nr, void *data) { DMA2_Stream7_IRQHandler(); return IRQ_HANDLED; } 

And then register this wrapper:

 irq_attach(DMA2_Stream7_IRQn + 16, embox_DMA2_Stream7_IRQHandler, 0, NULL, "DMA2_Stream7_IRQHandler"); 

You can see that the names of interrupt handlers in Cube have a well-defined structure - * _IRQHandler (as well as the names of interrupt numbers - * _IRQn ). Therefore, in order to automatically find all interrupt handlers for this example, we first go through the file with the cpp preprocessor, and in the resulting file we find all * _IRQHandler. And further, import_stm32_cube_example.py will generate the Src / embox_stm32f7xx_it_lib.c file, which will contain all the necessary interrupt handlers and the global function embox_stm32_setup_irq_handlers , the call of which is registered by interrupt handlers.

In addition to interrupts from the periphery, you need to remember about the hardware timer, since actions like filling audio buffers can occur in the Cube timer handler (it's called SysTick_Handler ). Therefore, the first level handler is the handler in Embox, which at the end will already call SysTick_Handler.

Finally, you need to fix the Src / main.c. First, the main function in the Cube examples always contains 3 standard calls - CPU_CACHE_Enable (), HAL_Init (), SystemClock_Config (). These functions and so are called when you start Embox, so in the example they are extremely harmful, therefore, they are automatically commented out. Last, the registration of interrupt handlers is added, i.e. view call

 if (0 != embox_stm32_setup_irq_handlers()) { printf("embox_stm32_setup_irq_handlers error!\n"); } 

The result is a full-fledged OS module, which can be immediately included in the config, pour Embox onto the board, and run as a normal command from the command line.

To demonstrate all of the above, I chose, as I said, two examples - 1) LCD screen 2) Example of recording audio from BSP.

For those who want to play with STMkoy below give links and recipes. Probably an article on how to build and run Embox comes in handy here.

LCD example on STM32F746G-Discovery

Go to the folder with Embox, and add an example:

# ./scripts/stm32/import_stm32_cube_example.py f7 ./build/extbld/third_party/bsp/stmf7cube/core/STM32Cube_FW_F7_V1.5.0/Projects/STM32746G-Discovery/Examples/LTDC/LTDC_Display_1Layer

This directory with a long name will appear after you first assemble Embox, during the build the archive will be downloaded from the STM32Cube under F7 and copied where needed.

Now an example LTDC_Display_1Layer will appear in the platform / stm32f7 / cmds / folder. You can go to the folder and see if you do not believe :)

Add it to the conf / mods.config config as stm32f7.cmd.LTDC_Display_1Layer. Reassemble Embox and load it on the net. In the minicom console, after loading mbox, we run the example using the LTDC_Display_1Layer command. On the screen will draw a picture of the girls.

Example with sound on STM32F746G-Discovery (+ Touchscreen)

Go to the folder with Embox, and add an example:

# ./scripts/stm32/import_stm32_cube_example.py f7 ./build/extbld/third_party/bsp/stmf7cube/core/STM32Cube_FW_F7_V1.5.0/Projects/STM32746G-Discovery/Examples/BSP

Now an example BSP will appear in the platform / stm32f7 / cmds / folder. This example demonstrates many of the features of the STM32F7-Discovery.

Add it to the config as stm32f7.cmd.BSP. Reassemble Embox and load it on the net. In the minicom console, after loading mbox, run the example with the BSP command. After launch, you can select the desired example by pressing the User Button (blue joystick) and start recording sound from microphones (MEMS microphones, miniature microphones embedded in the board), after which the recording will play after a few seconds.

Video with some examples from BSP.


The implementation can be viewed here .

That's all. We will be glad to questions.

Source: https://habr.com/ru/post/348930/


All Articles