I have a bare-metal program(driver) which reads/writes some memory-mapped registers. e.g:
void foo_read(uint64_t reg_base, uint32_t *out_value)
{
*out = READREG(reg_base + FOO_REG_OFFSET);
}
#define FOO_REG_OFFSET
0x00000123
). Register "foo" is 32-bit "wide".READREG is defined like this:
#define READREG(address) (*(uint32_t*)(address))
As you can guess MISRA 2008 is not happy with the cast from unsigned long long to pointer (5-2-7/5-2-8 are reported). My question is: what is the best/appropriate way to access memory and get rid of MISRA warnings? I've tried to cast to uintptr_t before casting to pointer, but This didn't help.
Thank you.
OK a few things here - first of all, your definition for READ_REG
is missing a volatile
-- it should be something like
#define READREG(address) (*(uint32_t volatile *)(address))
Secondly - and this is CPU-specific of course - generally speaking, reading a 32-bit value from an odd address (offset 0x123) won't work - at a minimum it will be slow (multiple bus cycles), and on many architectures, you'll hit a processor exception. (BTW, please note that pointer arithmetic doesn't come into play here, since the 2 values are added before being cast to a pointer.)
To answer your original question:
what is the best/appropriate way to access memory and get rid of MISRA warnings
Well -- you are violating a MISRA rule (you have to in this case, we've all been there...) so you will get a warning.
So what you need to do is suppress the warning(s) in a disciplined, systematic and easily identifiable way. In my opinion, there is no better example and explanation of this than in the Quantum Platform (QP) Event-driven framework's code, which is open source. Specifically:
Q_UINT2PTR_CAST
macro6.3 Rule 5-2-8(req)
An object with integer type or pointer to void type shall not be converted to an object with pointer type.
The QP/C++ applications might deviate from rule 5-2-8 when they need to access specific hard-coded hardware addresses directly. The QP/C++ framework encapsulates this deviation in the macro
Q_UINT2PTR_CAST()
. The following code snippet provides a use case of this macro:#define QK_ISR_EXIT() . . . \
*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
I don't have time to talk about MISRA warning suppresions, compliance issues, etc. but the above gives you everything you need.
P.S. Not sure which MISRA guidelines you are referring to -- for C, there are the 2004 & 2012 guidelines, and for C++, there are the 2008 guidelines (I know, it's almost 2017!)
User contributions licensed under CC BY-SA 3.0