2019-09-06 08:23 AM
The function LL_ADC_SetChannelSingleDiff() in stm32l4xx_ll_adc.h relies on
shifting a 32 bit value 32 postions in order to clear a bit field.
Shifting a word with >= the word size is undefined in the C standard and this
generates erronous code when compiled with for example gcc 7.2.1 and optimzation -O1.
This error is manifested in the function HAL_ADC_ConfigChannel() when initiating an ADC channel as single-ended it will be initiated as differential.
Complete compiler command used when problem occurred:
arm-none-eabi-gcc-7.2.1.exe -DARM_MATH_CM4 -DSTM32L432xx=1 -D__FPU_PRESENT=1 -D__FPU_USED=1U -mfloat-abi=hard -mcpu=cortex-m4 -mthumb -mlittle-endian -mfpu=fpv4-sp-d16 -ffunction-sections -std=c99 -fdata-sections -fverbose-asm -Wall -Wstrict-prototypes -Wdouble-promotion -g -gdwarf-2 -O1 -save-temps -Werror xxxx\stm32l4xx_hal_adc.c
Compiling with optimization -Og generates correct code.
Have tried both STM32Cube_FW_L4_V1.10.0 and STM32Cube_FW_L4_V1.14.0, which have slightly different implementations of "LL_ADC_SetChannelSingleDiff()", though both have undefined behavior according to the C standard, see for example:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
In section 6.5.7 Bitwise shift operators:
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
2019-09-26 08:02 AM
Hi @WNybe ,
I'll report this issue to our development team who should take relevant actions to fix it.
Thanks for bringing it to our attention.
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2019-09-26 08:19 AM
Hi @Amel NASRI
https://community.st.com/s/question/0D50X00009bLP0eSAG/adc-init-bug-with-optimization-o1-stm32l4
That's like more than a year.
Probably that's why Wilhelm fomulated this as a "has it been fixed?" question.
JW
2019-09-26 08:41 AM
Hi @Community member ,
As said by @WNybe , an update is done but didn't fixed the issue. I'll report it again.
-Amel
Internal ticket number: 72919 (This is an internal tracking number and is not accessible or usable by customers).
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2019-09-26 09:54 AM
Hi @Amel NASRI ,
Sorry for being rough.
Indeed, v1.14 has a different formula, instead of the standard-"violating" (0x7F<<0x20) in v1.12, this time reducing to
MODIFY_REG(ADCx->DIFSEL, Channel & 0x0007FFFF, (Channel & 0x0007FFFF) & (0x0007FFFF >> (0x7F & 0x18)));
or
MODIFY_REG(ADCx->DIFSEL, Channel & 0x0007FFFF, (Channel & 0x0007FFFF) & (0x0007FFFF >> (0x7F0000 & 0x18)));
and both should be OK as far as the quoted standard paragraph goes.
@WNybe ,
can you please post the disassembly at around the problematic place, preferrably mixed with the C source, exhibiting the problem, i.e. that incorrect value is written into ADCx->DIFSEL ?
Thanks
JW
2022-08-31 10:12 AM
The problem still exists in STM32Cube_FW_G4_V1.5.1. Has a work-around been posted? Or is the problem now with LL_ADC_GetChannelSingleDiff?
2022-09-01 08:52 AM
Hi @Community member ,
I received an answer from development team in 2019 saying that the problem wasn't reproduced using following configuration at that time:
In your current situation, could you please create a new thread where you describe your issue with more details (what you face exactly as issue? what are you using as environment? ...)
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.