I'm learning to use STM32 microcontrollers using CubeMX to generate a project. I've noticed that CubeMX generates two basic stages of initialization for nearly every peripheral:
(A) Within the stm32fxxxx_hap_msp.c
file, it defines a number of callbacks of the form HAL_XXX_MspInit()
.
(B) Within main.c
, it defines a number of functions of the form MX_XXX_Init()
.
Sometimes a given peripheral's HAL_XYZ_Init()
function is called from within (A) as it is with the ADC and RTC. Other times a given peripheral's HAL_XYZ_Init()
function is called from within (B) as it is done with GPIO.
Both sets of functions call __HAL_RCC_xxxx
macros extensively.
I can't make heads or tails of the usage pattern and neither the HAL guide nor reference manual give much direction here.
So, questions:
-
I suspect that the callback format provided by (A) has something to do with the uC waking from low-power modes, but I am not positive about this. Is this correct, or what is the purpose of the
HAL_XXX_MspInit
callback format? -
I noticed that (A) contains more user-definition block comments indicating room for my code to cohabit the functions generated by CubeMX. But why, for instance, would it be wrong to move code from (B) into the space of (A) in order to keep my initialization sequence clear and easy to read?
Best Answer
I was able to answer my own question.
The
HAL_XXX_MspInit()
functions are called by their respectiveHAL_XXX_Init()
functions. As an example, whenmain()
calls itsMX_I2C_Init()
, this prepares a global structure (defined in main.c) for initializing the I2C peripheral.The call stack goes (roughly, with omissions):
main()
[written by CubeMX]MX_I2C_Init()
[written by CubeMX]HAL_I2C_Init()
[provided by HAL Drivers and put inDrivers/
by CubeMX]HAL_I2C_MspInit()
[empty version provided by HAL Drivers, overrided by CubeMX inCore/Src/stm32fxxx_hal_msp.c
]Note that this means that you can call the
_MspInit()
and_MspDeinit()
functions during your code's runtime. You may choose to do this, for example, to change low-level resource state before or after a change in power modes.This answer (and other details concerning HAL call flow) is only hinted at by the Description of HAL and LL Drivers document, and is best confirmed by checking the HAL source code. This code is quite a bit more friendly than you might expect, and is located under your project tree under HAL_Drivers for any CubeMX project.