Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

71%
+3 −0
Q&A Declaring a callback function in usart.h, using it in usart.c but defining it in main.c

[ rb_put(UDR0) sounds like an AVR. I'll be using STM32 in some examples, because I'm not familiar with AVRs. You were asking about about STM32 on EE.Codidact recently. ] But I have a gut feeli...

posted 7d ago by Nick Alexeev‭

Answer
#1: Initial revision by user avatar Nick Alexeev‭ · 2026-09-10T02:14:57Z (7 days ago)
*[ `rb_put(UDR0)` sounds like an AVR.  I'll be using STM32 in some examples, because I'm not familiar with AVRs.  You were asking about about STM32 on EE.Codidact recently. ]*

> But I have a gut feeling that this is wrong. It feels wrong that I handle an intrinsic UART construct `UDRE0` in `main.c` when it feels like it belongs in `usart.c` .

You can factor out the serial packet handler into a separate .c file.  It would sit between `main.c` and `usart.c`  It may be possible to reuse it [with upgrades over time] across multiple projects.

<h3>UART transmission (TX)</h3>

Transmission on UART is the easy part.¹  Olin already mentioned that you can iterate through the buffer and call the equivalent of `putc(...)` for each byte.  

STM32 HAL has got a synchronous transmit function `HAL_UART_Transmit(...)` .  There's the DMA transmit function `HAL_UART_Transmit_DMA(...)`.  DMA lends itself well to transmission.

<h3>UART reception (RX)</h3>

Receiving on UART is always harder than transmitting.¹  The inconvenience with synchronous approach is that the `main()` always needs to poll the UART fast enough.  Receiving the UART bytes in the interrupt makes sure that none of them will be missed.

The UART on STM32 can receive variable length packets, and DMA them into memory.  It determines the end of a packet by the idle period after it.  There's one DMA interrupt at the end of the packet, and the complete buffer would be given to the packet processor.

¹ That's true for a lot of comms.  Usually it's easier to transmit well than to receive correctly.


<h3>Hard-coded callback</h3>

Your proposed way of creating a callback shows up once in a while.  I’ll refer to it as *hard-coded callback* [as opposed to function pointer callback], but I don’t know what this method is called actually.  For example, it shows up in the STM32 HAL.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* phAdc)

``` C
// @file    stm32g4xx_hal_adc.h
// @brief   Header file of ADC HAL module.

// ADC IRQHandler and Callbacks used in non-blocking modes (Interruption and DMA)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc);
// ...and there are more prototypes for callbacks there.
```

The HAL also provides a default implementation (a stub).  It’s declared with `__weak` so it can be overridden in another compilation unit.  The __weak keyword is not part of the C standard.  The GCC for AVR supports weak linkage via `__attribute__((weak))` .

``` C
// @file    stm32g4xx_hal_adc.c

__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  UNUSED(hadc);    /* Prevent unused argument(s) compilation warning */

  /* NOTE : This function should not be modified. When the callback is needed,
            function HAL_ADC_ConvCpltCallback must be implemented in the user file.   */
}
```