EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Missing volatile qualifiers in MCU vendor header files?

Started by Dave Nadler April 5, 2020
Whilst trying to track down an obscure bug, I noticed that ST
header files do not specify volatile for peripheral registers.
In contrast ARM stuff (looking at CMSIS) is religious about volatile.

For example, in stm32f413xx.h there's lots of stuff like
#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) // nice hex address
#define TIM2      ((TIM_TypeDef *) TIM2_BASE)  // TIM2-> used throughout

No volatile on the pointer declaration (nor structures wouldn't work for typedef?)

I checked some headers from Freescale/NXP (OK, a few years old), same thing.

Am I missing something, or is this omission completely nuts?
A lot of register access will be intolerant of 'optimization', right?
David B. ?

Thanks in advance,
Best Regards, Dave
Dave Nadler schrieb:

> Whilst trying to track down an obscure bug, I noticed that ST > header files do not specify volatile for peripheral registers. > In contrast ARM stuff (looking at CMSIS) is religious about volatile. > > For example, in stm32f413xx.h there's lots of stuff like > #define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) // nice hex address > #define TIM2 ((TIM_TypeDef *) TIM2_BASE) // TIM2-> used throughout > > No volatile on the pointer declaration (nor structures wouldn't work for typedef?) > > I checked some headers from Freescale/NXP (OK, a few years old), same thing. > > Am I missing something, or is this omission completely nuts? > A lot of register access will be intolerant of 'optimization', right?
Have a look at the definition of the structure (i.e. TIM_TypeDef), where all the variables have the attribute __IO which should make them volatile. Tilmann
On 6.4.20 01:00, Dave Nadler wrote:
> Whilst trying to track down an obscure bug, I noticed that ST > header files do not specify volatile for peripheral registers. > In contrast ARM stuff (looking at CMSIS) is religious about volatile. > > For example, in stm32f413xx.h there's lots of stuff like > #define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) // nice hex address > #define TIM2 ((TIM_TypeDef *) TIM2_BASE) // TIM2-> used throughout > > No volatile on the pointer declaration (nor structures wouldn't work for typedef?) > > I checked some headers from Freescale/NXP (OK, a few years old), same thing. > > Am I missing something, or is this omission completely nuts? > A lot of register access will be intolerant of 'optimization', right? > David B. ? > > Thanks in advance, > Best Regards, Dave
Just stay away from the hardware guys' software, write your own. I lost 6 weeks of debugging using Atmel's driver mess. The ST code is not any better. The CubeMX is good in handling the pin allocation puzzle, but I'd very careful about the offered software. -- -TV
On 2020-04-06, Tauno Voipio <tauno.voipio@notused.fi.invalid> wrote:

> Just stay away from the hardware guys' software, write your own.
Too true. Software provided by silicon vendors is consistenty awful. It tends to be bloated and full of errors. I don't know who they hire to write libraries and demo apps, but they haven't a clue. Usually the only thing that can be salvaged are header files with register offsets and bitmasks. Even then you have to double-check them for errors. -- Grant
On Mon, 6 Apr 2020 13:21:07 +0000 (UTC), Grant Edwards
<invalid@invalid.invalid> wrote:

>On 2020-04-06, Tauno Voipio <tauno.voipio@notused.fi.invalid> wrote: > >> Just stay away from the hardware guys' software, write your own. > >Too true. Software provided by silicon vendors is consistenty awful. >It tends to be bloated and full of errors. I don't know who they hire >to write libraries and demo apps, but they haven't a clue.
When a new engineer is hired, the first thing he/she has to familiarize with the company products. Making demo apps is a good way. Unfortunately, these private demo applications are published without checks by a more proficient person :-).
> >Usually the only thing that can be salvaged are header files with >register offsets and bitmasks. Even then you have to double-check >them for errors.
On Monday, April 6, 2020 at 2:29:39 AM UTC-4, Tilmann Reh wrote:
> Have a look at the definition of the structure (i.e. TIM_TypeDef), where > all the variables have the attribute __IO which should make them volatile.
Thanks Tilman! I missed that, from core_cm4 in both these instances...
On Monday, April 6, 2020 at 3:05:47 AM UTC-4, Tauno Voipio wrote:
> Just stay away from the hardware guys' software, write your own.
Yup, I had to write my own drivers for ST DMA, timer, SPI. But it gets quite impractical to write one's own drivers for every ethernet and USB peripheral set etc... And lots of the vendor stuff absolutely does not work (ST for example). Now if I could only figure out why my release build works, but not the debug build (reverse of the usual puzzle!)... Off to check the timing on the scope!
On Monday, April 6, 2020 at 9:54:58 AM UTC-4, Dave Nadler wrote:
> On Monday, April 6, 2020 at 2:29:39 AM UTC-4, Tilmann Reh wrote: > > Have a look at the definition of the structure (i.e. TIM_TypeDef), where > > all the variables have the attribute __IO which should make them volatile. > > Thanks Tilman! I missed that, from core_cm4 in both these instances...
PS: Really not where I expected! Better if ptr is volatile, not struct or fields. Explained well by David Brown here: https://embeddedgurus.com/barr-code/2012/11/how-to-combine-volatile-with-struct/
On 06/04/2020 23:36, Dave Nadler wrote:
> On Monday, April 6, 2020 at 9:54:58 AM UTC-4, Dave Nadler wrote: >> On Monday, April 6, 2020 at 2:29:39 AM UTC-4, Tilmann Reh wrote: >>> Have a look at the definition of the structure (i.e. TIM_TypeDef), where >>> all the variables have the attribute __IO which should make them volatile. >> >> Thanks Tilman! I missed that, from core_cm4 in both these instances... > > PS: Really not where I expected! Better if ptr is volatile, not struct or fields. > Explained well by David Brown here: > https://embeddedgurus.com/barr-code/2012/11/how-to-combine-volatile-with-struct/ >
Hey! A cite! I'm famous :-) The most important part is to have the volatile /somewhere/. An extra volatile in an access never makes a program incorrect, but a missing volatile in an access can make it subtly incorrect. The "best" place depends on how much control you want, how explicit you want to be, how much you understand things like ordering between volatile accesses and non-volatile accesses (there isn't any), how much you want to fight for the last drops of efficiency, and of course how clear the code is.
On Monday, April 6, 2020 at 6:09:56 PM UTC-4, David Brown wrote:
> Hey! A cite! I'm famous :-)
We already knew that ;-)

Memfault Beyond the Launch