Embedded code is a lot of fun, but if you want to safely work on the "really fun" stuff it's important to maintain a high level of quality and correctness for fundamental but lame utility functions like this. Otherwise you could literally build a ticking time bomb!
What I would do in this particular case is make a note of the limitations in the function block comment. There are always trade-offs in embedded code so I think it is fair to say that yes this code does not handle rollover, FYI.
The dislike for volatile coming from people in higher systems is pretty tiring and unwarranted.
Volatile is a perfectly fine tool on low level mcus.
It can be argued that the only kind of variable that can be shared safely between an ISR and the rest of the code is a volatile sig_atomic_t, but that is an argument from analogy and not from first principles, as the C abstract machine has no concept of ISR.
The same goes for the argument that you should use atomic intrinsics, plausible, but still just an analogy.
(Just in case anyone was wondering if C as a language is close to the metal: no, it is not.)
Not sure if OP is here, but I'd be interested in hearing about which debug options are easily exposed on that board. Can you use the port you are flashing the drone with as a standard serial port after your code is loaded? Looking forward to the future post about SWD that is introduced at the end of this post as well.
I think that the ALLCAPS parts come from acronyms in most cases. Like, NVIC = Nested Vector Interrupt Controller. The naming can get a little bit confusing, but it seems fairly consistent.
*(volatile uint32_t *)0x40021018 = 0x00000004;
volatile uint32_t* p = (volatile uint32_t *)0x40021018;
*p = 0x00000004;
The new cube library can be more complex.