HAL_ADC_ConvCpltCallback optimized away
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-15 11:39 PM - last edited on ‎2025-06-16 2:22 AM by Andrew Neil
Post edited to follow the community rules: Please review how to share a code in this post.
Using the stm32g030k8 and the Version: 1.18.1 STM32CubeIDE
I just recently applied an optimization in order to get more space for my application firmware. And then I realize that the HAL_ADC_ConvCpltCallback has been optimized away. I use the -Og (debug optimization) to use the less agressive and more debug friendly optimization.
__attribute__((used)) void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc1)
{
ADC_Average_Buff[CHANNEL_VREF] = ADC_DMA_Buff[CHANNEL_VREF];
ADC_Average_Buff[CHANNEL_VBAT] = ADC_DMA_Buff[CHANNEL_VBAT];
ADC_Average_Buff[CHANNEL_CURRENT] = ADC_DMA_Buff[CHANNEL_CURRENT];
ADC_Average_Buff[CHANNEL_TEMPERATURE] = ADC_DMA_Buff[CHANNEL_TEMPERATURE];
ADC_Average_Buff[CHANNEL_VREF] += ADC_DMA_Buff[CHANNEL_VREF];
ADC_Average_Buff[CHANNEL_VBAT] += ADC_DMA_Buff[CHANNEL_VBAT];
ADC_Average_Buff[CHANNEL_CURRENT] += ADC_DMA_Buff[CHANNEL_CURRENT];
ADC_Average_Buff[CHANNEL_TEMPERATURE] += ADC_DMA_Buff[CHANNEL_TEMPERATURE];
//-------------------------------------------------------------
if (ADC_Samples >= ADC_SAMPLES - 1)
{
//------------------------------
// Voltage Reference calculation
if (ADC_Average_Buff[CHANNEL_VREF] > 0)
{
VoltageReference_Dig = (uint16_t) ADC_Average_Buff[CHANNEL_VREF] / ADC_SAMPLES;
VoltageReference = (uint16_t) __LL_ADC_CALC_VREFANALOG_VOLTAGE( VoltageReference_Dig, LL_ADC_RESOLUTION_12B);
}
else
{
VoltageReference = VDDA_APPLI;
// WARNING: Measure error, action: pending.
}
//------------------------------
// Voltage Battery calculation
if (ADC_Average_Buff[CHANNEL_VBAT] > 0)
{
VoltageBattery_Dig = (uint16_t) ADC_Average_Buff[CHANNEL_VBAT]/ ADC_SAMPLES;
VoltageBattery_Pin = (uint16_t) __LL_ADC_CALC_DATA_TO_VOLTAGE( VoltageReference, VoltageBattery_Dig,LL_ADC_RESOLUTION_12B);
ConversionFloat_Auxiliar = (float) (VoltageBattery_Pin);
if (ConversionFloat_Auxiliar > 0)
{
ConversionFloat_Auxiliar = ((((ConversionFloat_Auxiliar / 1000) / ADC_VBAT_R2) * (ADC_VBAT_R2 + ADC_VBAT_R1)) * 1000)+ ADC_VBAT_OFFSET;
//ConversionFloat_Auxiliar /= 1000;
}
else
{
ConversionFloat_Auxiliar = 0;
}
VoltageBattery = (uint16_t)ConversionFloat_Auxiliar;
}
else
{
// WARNING: Measure error, action: pending.
}
//------------------------------
// Current Motor calculation
if (ADC_Average_Buff[CHANNEL_CURRENT] > 0) // index == 1
{
VoltageMotorShunt_Dig = (uint16_t) ADC_Average_Buff[CHANNEL_CURRENT] / ADC_SAMPLES;
VoltageMotorShunt_Pin = (uint16_t) __LL_ADC_CALC_DATA_TO_VOLTAGE( VoltageReference, VoltageMotorShunt_Dig,
LL_ADC_RESOLUTION_12B);
ConversionFloat_Auxiliar = (float) (VoltageMotorShunt_Pin);
if (ConversionFloat_Auxiliar > 0)
{
ConversionFloat_Auxiliar = (((ConversionFloat_Auxiliar / 1000)/ ADC_SHUNT) * 1000) + ADC_MOTOR_SHUNT_OFFSET;
}
else
{
ConversionFloat_Auxiliar = 0;
}
CurrentMotor = ConversionFloat_Auxiliar;
}
else
{
// WARNING: Measure error, action: pending.
}
//------------------------------
// Temperature calculation
if (ADC_Average_Buff[CHANNEL_TEMPERATURE] > 0)
{
Temperature_Dig = (uint16_t) ADC_Average_Buff[CHANNEL_TEMPERATURE] / ADC_SAMPLES;
Temperature = 100*(int16_t) __LL_ADC_CALC_TEMPERATURE(VoltageReference, Temperature_Dig, LL_ADC_RESOLUTION_12B);
}
else
{
// WARNING: Measure error, action: pending.
}
//------------------------------
// Initialization buffers
ADC_Samples = 0;
ADC_Average_Buff[CHANNEL_VREF] = 0;
ADC_Average_Buff[CHANNEL_VBAT] = 0;
ADC_Average_Buff[CHANNEL_CURRENT] = 0;
ADC_Average_Buff[CHANNEL_TEMPERATURE] = 0;
//------------------------------
//------------------------------
}
else
{
ADC_Samples++;
}
} // End HAL_ADC_ConvCpltCallback
As the reader can see, I have added the __attribute__((used)) but it is still being optimized away. I also check if the ADC_DMAConvCplt or HAL_ADC_IRQHandler or DMA1_Channel1_IRQHandler are being called, but they are not being called.
what should I do next?
Thanks for all.
- Labels:
-
ADC
-
DMA
-
STM32G0 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 12:19 AM
First, there is a "insert code sample" menu entry, which makes code snippets like yours much more readable.
Second, declare your ADC_Average_Buff array volatile.
It is highly recommended (read: required) for variables changed in interrupt context anyway.
> __attribute__((used)) void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc1)
It would be new to me that "__attribute__((used))" has any effect on functions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 1:59 AM
Hello @carlesls2
Did you try to disable optimization for the callback function?
#pragma GCC push_options
#pragma GCC optimize ("O0") // Disable optimization for this function
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
// Your callback implementation
}
#pragma GCC pop_options
Saket_Om
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 2:09 AM
what is push_options and pop_options?
#pragma GCC push_options
#pragma GCC pop_options
Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 2:19 AM
Hello @carlesls2
Please check the GCC manual.
Saket_Om
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 2:27 AM
@carlesls2 wrote:the HAL_ADC_ConvCpltCallback has been optimized away.
How are you sure that the function has been optimised away?
As @Ozone suggests, if you haven't qualified things which get modified in the callback as volatile, then accesses to those variables may get optimised-out.
@carlesls2 wrote:I also check if the ADC_DMAConvCplt or HAL_ADC_IRQHandler or DMA1_Channel1_IRQHandler are being called, but they are not being called.
Sounds like the hardware interrupts are not happening...
A complex system designed from scratch never works and cannot be patched up to make it work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 3:04 AM
I does not seem optimized away... it exists in the .map file. I guess this is not discarted... it seems not optimized away but it is never called. Yet this occurs when the optimization is applied.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 3:36 AM
These callbacks are called from within the interrupt handler - hence their name.
I don't use Cube/HAL code, so you would need to check the respective ADC interrupt handler implementation. But they are supposedly called from there.
Perhaps some conditional code, or some preprocessor conditions (#if <..>) applying.
You could set a debug breakpoint in the handler, and step through.
Only avoid opening a interrupt status register view.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-16 5:43 AM
> And then I realize that the HAL_ADC_ConvCpltCallback has been optimized away.
Why do you think it's optimized away? Convince us.
Ensure ADC_Average_Buff is set to volatile.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-17 12:52 AM
I am not sure but whenever the optimization is applied (when I apply the -Og optimization) the HAL_ADC_ConvCpltCallback is never triggered. The It may not be optimized away but this occurs because of the optimization.
I created a new smaller project to see if the HAL_ADC_ConvCpltCallback is being optimized away and it is not.
