Home > Software design >  MISRA rule 18.3 preventing copying data to RAM
MISRA rule 18.3 preventing copying data to RAM

Time:09-16

MISRA has a problem with the following code:

extern uint32_t __etext;
extern uint32_t __data_start__, __data_end__;
uint32_t* src = (uint32_t*)&__etext;        // ROM location of code to be copied into ram
uint32_t* dst = (uint32_t*)&__data_start__; // Start of RAM data section

while (dst  < &__data_end__) // Loop until we reach the end of the data section
{
    *dst   = *src  ;
}

I am getting a violation for rule 18.3:

The relational operators >, >=, < and <= shall not be applied to objects of pointer type except when they point to the same object.”

The rationale behind the rule is that attempting to make comparisons between pointers will produce undefined behavior if the two pointers do not point to the same object.

Why is this incorrect code? This seems like pretty generic boot code which is doing the right thing.

CodePudding user response:

MISRA C:2012 required Rule 18.3 is undecidable because it is often impossible to determine, statically, whether two pointers are pointing to the same object.

In the example cited, as long as you can demonstrate that the two pointers are, indeed, pointing to the same object (or block of memory) and that __data_end__ is higher up the memory map than __data_start__ then this is an easy documentation task.

s3.4 of MISRA Compliance applies - this appears to fall within Category (2). This is not the same as a formal deviation, but does still need appropiate review/signoff.

Whatever you do, do not change the code to try and create some clever mechanism that you claim is MISRA compliant!

CodePudding user response:

With linker defined symbols like this, the only way to satisfy this rule (without breaking 18.2 instead) is to cast the pointers to integers before comparing them. I don't think this change would help readability, so I would suggest making an exemption (called a "deviation record" in MISRA) and disabling the rule for this line of code.

CodePudding user response:

Why is this incorrect code? This seems like pretty generic boot code which is doing the right thing.

Because the code invokes undefined behavior, as specified by the C standard (additive operators 6.5.6/8), MISRA or no MISRA. For this reason, the compiler might generate incorrect code.

Possible work-arounds:

  • Create a big array or struct object covering the whole area to copy from and the area to copy into.
  • Use a compiler with a known and documented non-standard extension which allows you address absolute addresses regardless of what happens to be stored there. Then document it yourself in turn, in your MISRA documentation. (Most embedded compilers should support this. gcc might, but I don't know how without looking it up.)
  • Use integers instead of pointers and deviate from the MISRA rule regarding casting between integers and pointers. Which is an impossible rule to follow in embedded systems anyway.

Other problems:

  • (Severe) You have missing volatile bugs all over the code, which could result in incorrect code generation.
  • (Severe) You aren't using const correctness for variables stored in ROM which is surely a bug.
  • (Severe) Using extern in a safety/mission-critical application is highly questionable practice.
  • (Minor) Identifiers starting with double underscore are reserved by the compiler. If this code is from your home-made CRT it might be ok, but not if this code is from some generic bootloader.
  • (Minor) *dst = *src ; violates MISRA C 13.3. You need to do *dst = *src; dst ; src ;.
  • Related