Best way to avoid cast integer to pointer when dealing with memory access (MISRA 2008)

2

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);
}
  • reg_base is the base address of the memory-mapped device (64-bit address)
  • FOO_REG_OFFSET is the offset of the register (#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.

c
casting
embedded
bare-metal
misra
asked on Stack Overflow Oct 28, 2016 by AndreiSS • edited Oct 28, 2016 by juleslasne

1 Answer

1

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:

  • Check out the QP's MISRA Compliance matrix for examples of how this is handled -- for example, just search the PDF for the Q_UINT2PTR_CAST macro
  • Check out the QP's actual source code - for example, the macro that wraps/encapsulates such "int to ptr" casts (this way they are done in a manner that is easy to identify, and easy to change/suppress warnings for in a single place)
  • Lastly, check out the PC-Lint config file qpc.lnt, where you can see how/where the warnings are suppressed in a single place. THis is explained in this app note, section 6.3:

6.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!)

answered on Stack Overflow Oct 30, 2016 by Dan

User contributions licensed under CC BY-SA 3.0