cancel
Showing results for 
Search instead for 
Did you mean: 

How can I pass pointer info from hal_uart_receive_it into the callback function?

mikem1017
Associate II

I am trying to port over some code from PIC to STM32. In the pic code, the ISR took the pointer data from the received uart message (1 byte) and then sent that pointer data to a circular_buffer_put function (effectively putting it into the circular buffer).

The wall I'm running into is that the callback function is defined as only having one parameter - the huart handle - so I can't really do it the same way as before. All the examples I've seen online have the pointer data stored as a modular variable, which I'd really prefer not to do, and so the pointer data can be accessed in any function, including that of the callback.

Do any of you have a good idea on how to solve this problem?

Here's some example code of effectively what I'd like to do...

void HAL_UART_RxCpltCallback(uart_device_t *uart_struct, uint8_t *data)
{
    circular_buf_put(&RxBuffer, *data);
    HAL_UART_Receive_IT(uart_struct->huart, *data, 1);
}

14 REPLIES 14

Use some compound structure where you park the normal handle structure at the front, and your stuff at the back, and then cast what gets passed into the HAL, and what it hands back to you later.

typedef struct _UART_SUPER_HandleTypeDef {

UART_HandleTypeDef UartHandle;

// Your stuff

uint8_t *data;

int foo;

} UART_SUPER_HandleTypeDef;

UART_SUPER_HandleTypeDef Uart1;

Use &Uart1->UartHandle

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal

Very good suggestion Clive.

And as MCU have data in ram or flash, sub user blocks may have pointers to different memory.

It's honestly a pity that ST didn't think this through better and have a user data value or pointer within the original structure, or passed to the callbacks. The ability to link things seems like a very basic concept.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal

On my side sometime I use a "hook" which contains both a function pointer and a data context pointer to a user structure that can grow going up the sw layers. Type cast used to keep things tidy. Minimizing function passing parameters avoid filling up the core working registers that may not be used right away and could cause unseen performance losses.

Pavel A.
Evangelist III

> Use some compound structure where you park the normal handle structure

There's absolutely no need for such structure in this case.

The UART "handle" structure contains all the context about the completed operation (the buffer address, number of bytes read, status...). The callback can just use that.

A better idea is NOT to use the HAL for UARTs at all.

Thank you for the response. I am fairly new to all this (in fact I am a hardware engineer trying to learn some embedded). How would I 1) go about having the data pointer included in the uart handle structure? But more importantly 2) how do I not use Hal for this? Can you give me some example code on how I can write a uart receive interrupt with a call back including the passing of the data to a new function?

thank you!

Thank you so much for your detailed response!

Doesn’t the callback only take a handle though? If I do the method you mention, I’m still only sending it the handle right? How do I get the struct into the callback so that I can then pass the data to my circular buffer?

There actually is pointer value in the original structure I found... I'm just not sure whether I can use it. It's called *pRxBuffPtr. Any idea whether that's a pointer I can use?

typedef struct __UART_HandleTypeDef
{
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */
 
  UART_InitTypeDef              Init;             /*!< UART communication parameters      */
 
  const uint8_t                 *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
 
  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
 
  __IO uint16_t                 TxXferCount;      /*!< UART Tx Transfer Counter           */
 
  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
 
  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
 
  __IO uint16_t                 RxXferCount;      /*!< UART Rx Transfer Counter           */
 
  __IO HAL_UART_RxTypeTypeDef ReceptionType;      /*!< Type of ongoing reception          */
 
  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */
 
  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
 
  HAL_LockTypeDef               Lock;             /*!< Locking object                     */
 
  __IO HAL_UART_StateTypeDef    gState;           /*!< UART state information related to global Handle management
                                                       and also related to Tx operations.
                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */
 
  __IO HAL_UART_StateTypeDef    RxState;          /*!< UART state information related to Rx operations.
                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */
 
  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */
 
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
  void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart);        /*!< UART Tx Half Complete Callback        */
  void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart);            /*!< UART Tx Complete Callback             */
  void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart);        /*!< UART Rx Half Complete Callback        */
  void (* RxCpltCallback)(struct __UART_HandleTypeDef *huart);            /*!< UART Rx Complete Callback             */
  void (* ErrorCallback)(struct __UART_HandleTypeDef *huart);             /*!< UART Error Callback                   */
  void (* AbortCpltCallback)(struct __UART_HandleTypeDef *huart);         /*!< UART Abort Complete Callback          */
  void (* AbortTransmitCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Transmit Complete Callback */
  void (* AbortReceiveCpltCallback)(struct __UART_HandleTypeDef *huart);  /*!< UART Abort Receive Complete Callback  */
  void (* WakeupCallback)(struct __UART_HandleTypeDef *huart);            /*!< UART Wakeup Callback                  */
  void (* RxEventCallback)(struct __UART_HandleTypeDef *huart, uint16_t Pos); /*!< UART Reception Event Callback     */
 
  void (* MspInitCallback)(struct __UART_HandleTypeDef *huart);           /*!< UART Msp Init callback                */
  void (* MspDeInitCallback)(struct __UART_HandleTypeDef *huart);         /*!< UART Msp DeInit callback              */
#endif  /* USE_HAL_UART_REGISTER_CALLBACKS */
 
} UART_HandleTypeDef;

Hi @mikem1017​ 

1) you've already found the UART "handle" struct and the pointer. Yes, that pointer.

2) Sorry, I don't have a suitable example. But this is a frequent topic, there should be some examples around.

The complexity and size of the HAL code speaks for itself. It perhaps is good enough for demonstrating the hardware or a quick prototype, but one does not want this in a real product.

There is a well known collection of DMA based UART examples on github, but that is a higher level of complexity.