MISRA Rule 45

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hi!

I would like to define a pointer to a hardware register. I have done as follows:


typedef unsigned int Hw_Register;

volatile Hw_Register* const gp_dor_address = (Hw_Register* const)0x84501500;


When checking against MISRA I get the following error:

line 74: error #1703-D: MISRA Rule 45:
cast
          from type "unsigned int" to type "Hw_Register *" not allowed
  volatile Hw_Register* const gp_dor_address = (Hw_Register*
const)0x84501500;


How do I define a constant pointer to a register according to MISRA?

Regards,
Mikael Lundqvist

Re: MISRA Rule 45
Well,
I guess because you are hiding the unsigned int by a typedef.
MISRA rule 45 does not allow that.

Quoted text here. Click to load it

I guess you are in a dilemma here.

Hardware related implementations (no matter which compiler/toolchain)
usually employ coding mechanisms that MISRA rules see as "dangerous".
Which in a larger context of a huge application may make sense.
The low level stuff however is very hard - if not impossible - to implement
following MISRA.

Perfectly legal expressions (according to ANSI) like:

unsigned int *ptr;
ptr = (unsigned int *)0x67a9;

*ptr = 0xaa55;

*(int * const)(0x67a9) = 0xaa55;

Trigger a massive wave of MISRA error messages:

MISRA C rule 53 violation: [R] all non-null statements shall have a
side-effect
    17:  *(int * const)(0x67a9) = (unsigned int* const)0xaa55;
MISRA C rule 13 violation: [A] specific-length typedefs should be used
instead of the basic types
MISRA C rule 44 violation: [A] redundant explicit casts should not be used
MISRA C rule 45 violation: [R] type casting from any type to/from pointers
shall not be used
MISRA C rule 13 violation: [A] specific-length typedefs should be used
instead of the basic types
MISRA C rule 44 violation: [A] redundant explicit casts should not be used
MISRA C rule 45 violation: [R] type casting from any type to/from pointers
shall not be used
MISRA C rule 53 violation: [R] all non-null statements shall have a
side-effect

Anyone proficient in embedded C programming will use these expressions
(together with volatile) to describe Special Funtion Registers or device I/O
adresses.

At best you disable MISRA for hardware dependend modules, document why you
have done so and use lint to check for any suspicious code constructs.


regards
/jan

snipped-for-privacy@posting.google.com...
Quoted text here. Click to load it
follows:
Quoted text here. Click to load it
const)0x84501500;
Quoted text here. Click to load it



Re: MISRA Rule 45

Quoted text here. Click to load it
You could also define all the relevant symbols in an assembly file, then
define the symbols as "extern" in your code.

If MISRA has some way of temporarily turn off a rule (i.e. with a
"#pragma" command or the like) then it may be a good thing to do, with a
slew of comments as to why you're doing it.

--

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: MISRA Rule 45
Tim,
thanks for your comment
Quoted text here. Click to load it

Again, as you mention it, MISRA is circumvented.
This is one way to do it. But Assembly is not really necessary.
The same can be done in C.
Another detour is the creation of object files or a library containing 'Non
MISRA checked' functions with proper protoyping.

There are tools on the market that allow to disable MISRA rules or use
special configuration files.
One thing common to all: Proper documentation is mandatory.


with kind regards
/jan




Re: MISRA Rule 45
Quoted text here. Click to load it

Registers don't have addresses whose value can be taken.  This is
illegal in any form of C.

Quoted text here. Click to load it

legal, but not portable.

Quoted text here. Click to load it

perfectly legal anywhere, provided ptr has been initialized to
point somewhere legal.

Quoted text here. Click to load it

You can't cast the lvalue.  You can only cast the value to be put
into it.  Illegal everywhere.

Quoted text here. Click to load it

You shouldn't need the assistance of MISRA to avoid those
particular foul-ups.  

BTW, please don't top-post, and please do snip.  The practice of
top-posting a complete snipped bottom posted message only clutters
the world with further useless verbiage.

--
"If you want to post a followup via groups.google.com, don't use
 the broken "Reply" link at the bottom of the article.  Click on
We've slightly trimmed the long signature. Click to see the full one.
Re: MISRA Rule 45

Quoted text here. Click to load it

You've never worked on a processor, whose initial register set starts
at address 0? Very handy to run a programm just out of the registers,
especially when testing core memory!

Andreas
--
It's not the things you don't know what gets you into trouble. It's
the things you do know that just ain't so.
We've slightly trimmed the long signature. Click to see the full one.
Re: MISRA Rule 45
Quoted text here. Click to load it

Come now, "memory mapped register" is surely a fairly common usage.  And
referring to memory as a "register file" may be old-fashioned but I do
seem to recall seeing the term in documentation recently (just don't ask
me for a reference).


Quoted text here. Click to load it

On the other hand, peripheral reigster definition is pretty much
inheritly non-portable.


Robert

Re: MISRA Rule 45
Quoted text here. Click to load it

Well, it's a GCC extention. So, while it's not (std.) conformant, it's not
'illegal everywhere' either.

Regards,
Andras Tantos



Re: MISRA Rule 45
Quoted text here. Click to load it

registers can be memory mapped, and I think here we are talking about
memory mapped hardware registers not cpu registers.

who else would you access memory mapped registers in peripherals?

Quoted text here. Click to load it

doesn't have to be, what ever is at 0x67a9 in this
micro will probably be some where else in another.

but it would be nicer to use a define or somthing.



Quoted text here. Click to load it

hmm...

compiles with gcc and does what I'd expect; write the value 0xaa55
to adress 0x67a9 using STR

Quoted text here. Click to load it


-Lasse


Re: MISRA Rule 45
Quoted text here. Click to load it

I don't have a compiler or tool that complains about the above, other
than noting that the "const" is meaningless.  What in the standard
indicates this is illegal?

--
John W. Temples, III

Re: MISRA Rule 45

Quoted text here. Click to load it

It isn't casting an lvalue it is casting a constant to a pointer which is
dereferenced to yield an lvalue.

Re: MISRA Rule 45
Quoted text here. Click to load it

Touche.  A point, a veritable point.

--
"If you want to post a followup via groups.google.com, don't use
 the broken "Reply" link at the bottom of the article.  Click on
We've slightly trimmed the long signature. Click to see the full one.
Re: MISRA Rule 45
Quoted text here. Click to load it

This case would be more clear with other way
of setting the parentheses:

*((int *)0x67a9) = 0xaa55;

(The example is bad, many architectures are not happy
with a longer datum (int, 16 or 32 bits) loaded to
an odd address).

--

Tauno Voipio
tauno voipio (at) iki fi


Re: MISRA Rule 45
programmer snipped-for-privacy@hotmail.com says...
Quoted text here. Click to load it
follows:
Quoted text here. Click to load it

Two options AFAIK

1- if your linker supports it you can define it there.  GNU ld can be
used in that fashion.
2- Use MISRAs exception capability and use the form you are using but
document it as an exception.  At least the last revision of MISRA I read
had a provision for exceptions.

Robert

Re: MISRA Rule 45

Quoted text here. Click to load it
[...]
Quoted text here. Click to load it

The main problem is that you even tried to apply a portability /
safety oriented C coding ruleset such as MISRA to this strictly
hardware-specific task.  That makes no sense.

Quoted text here. Click to load it

You don't.  You might as well try to make an omelett according to a
"no breaking of eggs" standard.

--
Hans-Bernhard Broeker ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Re: MISRA Rule 45

Quoted text here. Click to load it

Since, somewhere in the code, there HAS to be a translation point
between the 'standard' language and something that accesses the
underlying hardware, how does the MISRA standard suggest this be done?

No use saying "do it in assembler"- a safety and portability standard
couldn't even contemplate such. A HAL shunts the problem a stage down
the line, but it's still necessary somewhere.

Paul Burke

Re: MISRA Rule 45

Quoted text here. Click to load it

The _best_ thing to be said of MISRA is that it recognizes it is
unreasonable to expect complete compliance, that the rules will have
to be broken from time to time (indeed, rule 3 says "break rule 1" in
almost so many words), and gives a procedure for doing so.

In MISRA 1, it is described in section 5.2.3 "Deviation procedure."  I
don't have a copy of MISRA 2 yet...

Regards,

                               -=Dave
--
Change is inevitable, progress is not.

Re: MISRA Rule 45
Hi all,
As a followup to CBFalconer's contribution and the resulting discussion:
It is always possible to find a hair in the soup. ;-)

To clarify some issues:
The example was taken from an article in the embedded systems programming
magazine (Programmer's test) which I find very enlightening because it
reflects 99% of the C language related support questions I get to handle
every day.

The 'registers' I was mentioning were meant to be so called Special Function
Registers of peripherals on an MCU.

It is common procedure (as with many toolchains I know) to implement header
files for MCU derivatives this way.
This goes for GNU as well as vendor specific tools alike.

Before posting I have tested the example with a little testcase.

The example:

unsigned int *ptr;
ptr = (unsigned int *)0x67a9;

*ptr = 0xaa55;

*(int * const)(0x67a9) = 0xaa55;



should better have been posted like:

/******* memio.c ********/
volatile unsigned int* SFR_IO_addr = (volatile unsigned int* )0x1500;

unsigned int *ptr;

void foo(void)
{
 ptr = (unsigned int *)0x67a9; /* assign address */
 * ptr = 0xaa55; /* store datum into address */
 *(int * const)(0x67a9) = 0xaa55; /*The expression is legal but somewhat
cyptic.*/

 while(*SFR_IO_addr==0)
 {
   ; /* wait forever while SFR_IO_addr = 0 */
 }
}

void main(void)
{
 foo();
}

/******* EOF memio.c ********/
So we do not run into the 'uninitialized pointer' issue CBFalconer
mentioned.

I hope this clears the fog a bit.

with kind regards
/jan



Site Timeline