3

I am performing a pointer assignment in an Embedded C script like so:

uint32_T *a = (uint32_T *) (4096U); 

Basically, I need a to point to the address location 4096 (decimal)

I get the MISRA warning as specified in the title (I use Code Composer Studio's MISRA C:2004 checker).

How can I fix this warning?

PS: uint32_T is a typedef for unsigned long

  • 1
    Why not use [uintptr_t](https://docs.oracle.com/cd/E19455-01/806-0477/chapter3-10/index.html)? – David Ranieri Jun 05 '20 at 05:13
  • replacing uint32_t with uintptr_t doesn't erase the warning – ANUBHAV DINKAR Jun 05 '20 at 05:28
  • I agree, and this code looks ok from my point of view. – mar Jun 05 '20 at 05:29
  • 1
    Duplicate of https://stackoverflow.com/questions/36552165/misracast-between-a-pointer-to-volatile-object-and-an-integral-type (The question is a bit different, but the answer applies to your case) – Catch22 Jun 05 '20 at 05:45
  • I am using Code Composer Studio. not sure how to check which specific compiler it uses – ANUBHAV DINKAR Jun 05 '20 at 05:46
  • 1
    I work in an environment where casts like that are quite MISRA forbidden, for exactly the reasons MISRA pursues. However in a specific area, this kind of casts is extremely common and follow a specific purpose (namely access to memory-mapped perihperals). I have managed to get all relevant parties (superiors, quality engineering, requirement engineering, ...) to agree that the rule is basically applicable and to be obeyed but that for exactly the special area it is allowed because necessary. I.e. I got a "blanko pass" to ignore these warnings and trust to decide when, provided that I doc it. – RubberBee Jun 05 '20 at 06:13
  • 1
    For me (or more importantly for the mentioned other people) that answered the question. Not sure whether it is considered an answer here on StackOverflow. Please let me know whether it should be turned into an answer. – RubberBee Jun 05 '20 at 06:17
  • I guess an answer will be fine – Mike Jun 05 '20 at 06:26
  • Did you try with `volatile`? ( `volatile uint32_T *a = (volatile uint32_T *) (4096U);` ) – HamidReza Jun 05 '20 at 06:44
  • 4
    @RubberBee You can't do microcontroller programming without breaking the rule. It's kind of essential to utilize MCU hardware registers in order to make anything function at all. All "relevant parties" should realize as much instantly, or they aren't competent enough to make any calls about MISRA-C what-so-ever. Basically, the only sensible way to work with MISRA-C is to have the most seasoned C veteran in the team make all the calls. Otherwise it will become a burden instead of an asset. It's a great document if used correctly, but only then. – Lundin Jun 05 '20 at 07:02
  • @Lundin That is exactly what I mean/meant. The point is of getting the parties to ***officially*** agree. Then you can refer to that whereever the warning occurs and walk free. – RubberBee Jun 05 '20 at 07:17
  • @RubberBee I can see how it would quickly turn bureaucratic and burdensome if you integrate MISRA-C deviations in the regular quality control system. Better to have a technical coding standard written by/for the programmers only, and collect all company-wide allowed deviations there. – Lundin Jun 05 '20 at 07:42
  • 1
    @Lundin You are right. That would be the logical thing to do. I envy you if you work in an environment in which the logical thing is what rules decisions and where this kind of bureaucracy happens within one programmers life time. A little exaggeration here... I think, because of my repeated example of confidently documenting and sticking with the code has achieved an implicit general permission by now... – RubberBee Jun 05 '20 at 07:45
  • Does `uint32_T *a = (uint32_T *) (void *) 0x1000U;` also complain? – chux - Reinstate Monica Jun 05 '20 at 11:51

3 Answers3

6

This is the kind of MISRA-C rule not to take too serious in itself - the rule is advisory and is mostly there to force programmers to think twice and study, before they do something which is potentially dangerous.

There are numerous pitfalls in integer to pointer conversions:

  • Alignment.
  • Different size or representation between pointers and integers.
  • Trap representations, including hardware exceptions and invalid addresses.
  • Type compatibility issues and strict pointer aliasing.

The average programmer is typically not aware of all of the above. And if they aren't, such integer to pointer conversions may be dangerous.

You must know in advance that the address pointed at is valid, and it makes sense to de-reference it with the picked type. For example, if you know that there is a 32-bit hardware register at that memory address, it's perfectly fine to de-reference through a uint32_t* pointer.

You must also know the pointer format for the given system. On 32 bit systems they are typically just 32 bit addresses. On smaller system like 8/16 bit CPUs, you may have different pointer types with sizes between 16 to 24 to 32 bits, making things more complicated.

Summary: if you know what you are doing, you can ignore this advisory MISRA-C rule.


Other issues with your code:

  • Don't use homebrewed integer types, use stdint.h. If you are stuck with C90, then define types with the same name as those in stdint.h and use those.
  • Casting from a memory address to a pointer without using volatile is almost certainly wrong. The compiler doesn't know what's stored there, and may make strange assumptions and incorrect optimizations if you don't volatile-qualify the pointer. And if it's a hardware register or NVM memory, it may change at any time, and must be volatile for that reason too.

Corrected code should be: volatile uint32_t *a = (volatile uint32_t*)4096U;

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

I work in an environment where casts like that are quite forbidden, for exactly the reasons MISRA pursues.
However in a specific area, this kind of casts is extremely common and follow a specific purpose (namely access to memory-mapped perihperals, especially in environments like embedded microcontrollers).

I have managed to get all relevant parties (superiors, quality engineering, requirement engineering, ...) to agree that the rule is basically applicable and to be obeyed, but that for exactly the special area it is allowed because of being necessary.
I.e. I got a "blanko pass" to ignore these warnings and enjoy the trust to decide when, provided that I document it. Of course this means also to not ignore it in other cases.

So this does not address the question of how to fix it in the code, but it does answer the question of how to avoid trouble because of it in environments where MISRA code checkers are a relevant part of making accepted software.

RubberBee
  • 150
  • 9
0

There is a reasonably good rationale for the Rule - and other than dealing directly with memory mapped registers, it's a very valid Rule.

But MISRA is itself aware that occasionally, Rules need to be violated... which is why we have a deviation process, documented in MISRA Compliance.

In fact, in the specific instance of memory mapped registers, we've even created a permit to aid the deviation. Currently permits only exist for MISRA C:2004 but will be coming for 2012 in due course.

Andrew
  • 2,046
  • 1
  • 24
  • 37