Application Notes | A brief discussion of the callback functions in the STM32 library
Catalog preview
1.Callback function
2. Callback function in STM32 firmware library
3. Callback mechanism and trigger events in STM32 library functions
4. Frequently Asked Questions
Some people are curious or even confused about the callback function in the STM32 firmware library. Here is a brief introduction for reference. In fact, there is nothing special about them in terms of usage and function. Like other functions, they are also code segments that implement specific functions. Generally speaking, the so-called callback function refers to a function that is called and executed based on an event trigger. To put it simply, it is a function that is called when the conditions are met. It is often combined with a function pointer to implement the call through the function pointer.
Often people introduce callback functions based on code like the following:
In the above code, the four functions related to addition, subtraction, multiplication and division can be regarded as callback functions. When they are called, according to the function Compute(float a, float b, float(*Action)(float a, float b)) Depending on the assignment of the function pointer, which callback function is called with the address assigned to it. Of course, using function pointers is not the core feature of callback functions. Being called event-driven is its core feature.
In life, we sometimes say to someone, talk about it later, talk about it later. The subtext is often to wait for the time to mature and the conditions to be met before negotiating in detail. There is a strong sense of callback here.
The callback function can be understood as an event response function or an event-driven function. Even if the same event may have different responses based on different scenarios, from the perspective of software code, it corresponds to different callback function codes.
Let’s look at an example from life. Someone in life has won the Mark Six Lottery. In response to this incident, the winner may have done one of the following things [simplified here, choose one from multiple times]. But if this happens to different people, the choice on the right is likely to be different. In other words, if you win the lottery, which one on the right you will choose depends on the specific person.
Figure 1 Possible subsequent behavior of Mark Six Lottery
Let's switch to the embedded development of STM32, taking the UART reception completion event as an example. In response to this incident, the responses to different application scenarios are often varied and colorful.
Figure 2 Possible subsequent actions after UART reception is completed
Obviously, specific application scenarios correspond to specific callback functions. Generally speaking, it is impossible to simply develop a piece of code that is applicable to various scenarios and is highly targeted based solely on events.
Combined with the above description, let’s briefly summarize. In addition to being called and executed based on the triggering of an event, callback functions also have the characteristic that the same event may require different callback functions in response to different application scenarios. That is, the content of callback functions based on specific application scenarios is specific.
Callback function in STM32 firmware library
Speaking of which, let’s talk specifically about the callback functions in the STM32 peripheral firmware library.
First of all, as a function library, except for individual initialization functions, there are no existing complete callback functions . Based on the previous introduction, we know that the callback function needs to be formulated based on specific scenarios. As a function library, it cannot do this at all. It cannot know in advance what operations different applications will need to take when a certain event occurs.
Secondly, the STM32 library function does use a callback mechanism, and reserves empty callback functions for STM32 developers with only function definitions and no specific content based on various possible events , or only defines some function pointers based on various events. , the specific callback function needs to be completed by the user and assigned the function address to the corresponding function pointer to be called. To put it simply, the function library has reserved many callback function interfaces for us in advance .
The callback function in the STM32 firmware library uses two calling methods:
The first is the legacy method, the traditional callback method. The library defines various empty callback functions in weak mode, like the following. STM32 library is ready for us. [The following is the weak callback function body related to some UART events, the content is empty]
Figure 3 UART transmission event-related weak callback function definition
During specific development, we rewrite based on weak functions similar to the above according to events and application scenarios. We remove the weak when rewriting, and try not to touch the weakly defined functions reserved in the library. For example, these are the final user callback functions.
Figure 4 User callback function related to UART transmission events
The other is the pointer method , or registration method . That is, the function library has defined various callback function pointers based on various events in advance. The specific callback function is written by the user based on different events and application requirements, and then the function address is assigned to the function pointer. This action is called a callback function. After registration , the callback function can be called timely through the function pointer.
For example, the following are some function pointers defined in the UART peripheral: [The asterisk refers to the pointer used by the callback function related to the UART transmission completion event]
Figure 5 Callback function pointer related to UART transmission events
After we write the callback function, assign the function address to the function pointer and it can be called when the corresponding event occurs. For example, the operation code is similar to the following. The code pointed to by the red star is registering the callback function.
Figure 6 UART transmission completion event user callback function and registration
Assigning an address to a function pointer can be done directly or by calling the library function xxx_RegisterCallback [see the star code above].
This pointer method requires us to have a corresponding understanding of structures and function pointers in C language. The library only provides us with the corresponding function pointers. The specific user callback function is written by the user as needed , and its address is assigned to the corresponding function pointer for calling.
As for the traditional callback functions introduced earlier, the library helps us prepare all the callback functions that may be involved in a weakly defined way. We can select them as needed and eliminate the weak fill-in-the-blank rewriting. It is relatively more intuitive to use and does not require us to know much about function pointers.
In the current STM32 library callback mechanism, which of the above callback methods should a user use? In the configuration header file of each series of firmware libraries, there are options for using callback functions for each peripheral event . For example, taking the STM32F4 series as an example, here is the header file stm32f4xx_hal_conf.h. We can see that based on each peripheral Macro for event callback function usage selection.
Figure 7 Selection and configuration of callback function calling method
If we do not adjust the macro definition of the callback function calling method of the corresponding peripheral event in the header file, the traditional callback method will be defaulted, that is, the legacy method, not the pointer method. If the corresponding macro value is changed to 1, the peripheral event-related callback function uses pointer registration.
Overall, the API functions in the STM32 peripheral library are generally composed of three parts, namely:
initialization function
startup execution function
Callback function [weakly defined function or callback function pointer, ultimately written by the user]
This arrangement makes the entire project code structure clearer, allowing people to quickly understand the library structure. At the same time, the existing API functions greatly reduce the development workload. The reserved callback function interface provides convenience to developers on the one hand, and allows developers to Users can freely organize codes based on different application scenarios without destroying the entire software architecture.
For callback functions, what events can be triggered? They are roughly divided into three categories, namely peripheral initialization operations, peripheral processing completion [interrupt] events, and peripheral error [interrupt] events. We pay most attention to the callback functions related to peripheral processing completion interrupt events .
Figure 8 Classification of events triggered by callback functions
4.1 What is the callback function in the STM32 library function and what is its use?
After all, the callback function is written by the user. It is a functional module written by the user based on specific events and application requirements. It is not essentially different from other functions. Formally speaking, the STM32 library pre-defines weak definitions of callback functions or definitions of event-based function pointers for users. It is called a callback because it is called after a specific condition occurs.
Strictly speaking, there are no complete callback functions in the library functions, only weakly defined empty callback functions without actual functions based on various events, or various function pointers for calling callback functions defined for various events. . Our programs often monitor corresponding conditions or events in a targeted manner . When corresponding events occur, we need to handle them accordingly. This is exactly what the callback function is supposed to do and where its function lies.
4.2 What is the difference between callback functions and interrupt functions in STM32 projects?
The callback functions in the STM32 peripheral library are indeed closely related to interrupt events and interrupt service programs most of the time. Corresponding user callback functions are often called based on specific events in the interrupt service program. Many times, we can regard the user callback function as a calling module or extension of the interrupt function.
An interrupt service routine can call different callback functions due to different events, that is, an interrupt service routine may contain multiple different callback functions. For example, we can involve multiple events and corresponding user callback functions in the timer interrupt service program. The timer interrupt service program may involve update events, comparison events of different channels, or capture events. The corresponding user callback functions often vary depending on the application scenario. Varies.
Of course, the callback function can also be triggered by events other than interrupt events. For example, the corresponding initialization callback function can be called based on the initialization operation. Of course, there may be some default operations for initializing a certain peripheral in the library, but this default operation is difficult to be universally applicable. At this time, we have to write targeted initialization code according to the actual application, that is, initialization type Callback.
4.3 Can the callback function in the STM32 library function be dispensed with?
The callback mechanism in the STM32 library function is a function declaration and interface prepared in advance by the library designer in order to facilitate the clarity of the software framework and reduce the developer's workload. When using it, users only need to write the relevant function body according to the specific application. Of course, it's okay if you don't want to ignore these callback function declarations and definitions. It's entirely feasible for you to organize the code yourself according to the specific application.
4.4 There seems to be a semi-finished library callback function in the STM32 library function?
The STM32 library function does prepare some library-defined callback functions that include user callback functions. They are callback functions prepared by library designers based on various specific events. They will do some basic and necessary operations for specific events, such as status. Checking, flag monitoring and clearing, but it cannot be completely written because it cannot know what the user's real needs are after the event occurs and how to operate it, so it still needs to call the real user callback function after all . The purpose of this is to reduce the development workload and errors for developers.
Let’s look at an example in detail. The following callback function samples the pointer registration method. Let's look at the calling process of the callback function after the transfer is completed in the UART's DMA transfer completion interrupt.
First, there is this part in the UART DMA startup function HAL_UART_Transmit_DMA():
Figure 9 Assignment of library callback function in peripheral startup and running code
Curry has prepared several callback functions for DMA transfer events [transfer complete, semi-complete, error], which are marked by the red line in the picture above. In fact, these callback functions are not complete user callback functions. They are defined by the library and will do some operations that it thinks the user must complete. It helps complete them in advance, and then calls the final user callback function . Let's take the transfer completion event as an example to see the function marked with an asterisk in the above figure.
Figure 10 The library callback function further calls back the user callback function
In the UART_DMATransmitCplt() function defined by this library, it determines the DMA transmission mode. If it is Normal mode, the UART transmission data length is set to 0, the DMA subsequent transmission function is disabled, and the UART transmission completion interrupt is enabled. Enable. Then call the user callback function [pointed by the arrow in the picture above]. If the DMA is working in loop mode, the code directly calls the final user callback function after entering the UART_DMATransmitCplt() function . In other words, the callback functions defined by these libraries perform some necessary operations on the basis of user callback functions. User callback functions can be regarded as a subset of such library callback functions.
4.5 What should we pay attention to when organizing user callback functions based on the STM32 library?
As mentioned earlier, user callback functions are mainly code organized based on initialization events or interrupt events. The calls to callback functions for interrupt events basically occur in the interrupt service routine. Therefore, when writing callback functions, we must flexibly organize the code according to the specific situation. Consider interrupt priority, real-time response to specific events, etc. To be more specific, when we organize the callback function, we must consider whether it must be written all in the interrupt service routine, and whether it will affect other interrupt responses. For some event response codes that are not urgent but time-consuming, you can consider only setting the corresponding flags in the callback function and placing the actual processing code in the main loop.
Also a reminder, the STM32 library designers took the initiative to prepare for us weakly defined callback functions or callback function pointers based on various events. Although it is very rich, it may not be all-inclusive. If necessary, we may have to organize some additional similar ones based on the specific situation. The event/interrupt response code of the callback function.
This is a brief introduction to the callback functions in the STM32 HAL library. I hope it can help some STM32 developers.
Follow STM32
▽ Click "Read Original" to download the original document