Skip to main content
Graduate
March 11, 2025
Question

Custom context in callback handlers

  • March 11, 2025
  • 3 replies
  • 691 views

Hello,

I would like to request a feature to be added to the STM32 HAL.

Would it be possible to be able to add a custom user context when registering peripheral callbacks.

Example:

 

HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, pSPI_CallbackTypeDef pCallback, void* UserContext);

 

And then as callback function:

 

typedef void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi, void* UserContext);

 

I really miss this feature and have had to code around it for god knows how many times.

I have added it myself to the SPI driver, but if I regenerate its all gone ofc.

So it would be real nice if this could be added to drivers.

 

Thx,

Alexander

    This topic has been closed for replies.

    3 replies

    Super User
    March 11, 2025

    I have added it myself to the SPI driver, but if I regenerate its all gone 

    To avoid losing your changes in the HAL libraries:

    - When you use Cube to (re)generate code, select the option to create links to the libraries instead of copying all the files into your project. 

    - Check your changes in the ST libraries into your version control (yes, make your private branch).

    To minimize code differences, do not pass the UserContext as a new argument. Instead, add it to the SPI_HandleTypeDef struct. Then your callbacks will get this arg from the hspi pointer: hspi->UserContext.

     

     

    Super User
    March 11, 2025

    @Pavel A. wrote:

    To minimize code differences, do not pass the UserContext as a new argument. Instead, add it to the SPI_HandleTypeDef struct.


    @Alexander4 there was some discussion of this in the 2021 thread:

    https://community.st.com/t5/stm32-mcus-embedded-software/is-there-a-way-to-provide-context-pointer-to-hal-callback/m-p/182064

    Graduate II
    March 12, 2025

    I agree it should have been added to the function argument or to the handler struct.

    Alternatively you can create a mapping table.

    Some pseudocode:

     

    typedef void (*usercallback_t)(SPI_HandleTypeDef *hspi, void* usercontext);
    
    typedef struct
    {
     void *peripheral;
     void *usercontext;
     usercallback_t function;
    } usercontext_mapping_t;
    
    static usercontext_mapping_t mappingtable[N];
    
    void callback(SPI_HandleTypeDef *hspi)
    {
     if (hspi == NULL) return
    
     for(int i=0;i<N;++i)
     {
     if(mappingtable[i].peripheral == hspi->instance)
     {
     if (mappingtable[i].function != NULL)
     {
     mappingtable[i].function(hspi, mappingtable.usercontext);
     } 
     break;
     }
     }
    }

     

     

    Create a wrapper function around HAL_SPI_RegisterCallback that automatically registers the function and adds user context to the table. You can also wrap the deregister function.

    I prefer creating wrapping functions over rewriting part of the functions. While it adds some overhead in terms of stack and CPU time that usually is not a problem. Once it becomes a problem I would switch from HAL to LL and write my own library.