MISRA Discussion Forums

Full Version: Rule 8.10 Register Mapping
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
I am using IBM logiscope to bring a pic24 project to MISRA compliance.

Due to the use of unions in the standard PIC header file (which maps all the registers to the locations in the linker) I have created my own local register mappings whenever needed.

i.e. for PORT configuration source, the header contains
Code:
extern volatile unsigned int  TRISA;
typedef struct
{
  unsigned TRISA0:1;
  unsigned TRISA1:1;
  unsigned TRISA2:1;
  unsigned TRISA3:1;
  unsigned TRISA4:1;
  unsigned :2;
  unsigned TRISA7:1;
  unsigned TRISA8:1;
  unsigned TRISA9:1;
  unsigned TRISA10:1;
} TRISABITS;
extern volatile TRISABITS TRISAbits;

extern volatile unsigned int TRISB;
typedef struct
{
  unsigned TRISB0:1;
  unsigned TRISB1:1;
  unsigned TRISB2:1;
  unsigned TRISB3:1;
  unsigned TRISB4:1;
  unsigned TRISB5:1;
  unsigned TRISB6:1;
  unsigned TRISB7:1;
  unsigned TRISB8:1;
  unsigned TRISB9:1;
  unsigned TRISB10:1;
  unsigned TRISB11:1;
  unsigned TRISB12:1;
  unsigned TRISB13:1;
  unsigned TRISB14:1;
  unsigned TRISB15:1;
} TRISBBITS;
extern volatile TRISBBITS TRISBbits;

extern volatile unsigned int  TRISC;
typedef struct
{
  unsigned TRISC0:1;
  unsigned TRISC1:1;
  unsigned TRISC2:1;
  unsigned TRISC3:1;
  unsigned TRISC4:1;
  unsigned TRISC5:1;
  unsigned TRISC6:1;
  unsigned TRISC7:1;
  unsigned TRISC8:1;
  unsigned TRISC9:1;
} TRISCBITS;
extern volatile TRISCBITS TRISCbits;

extern volatile unsigned int  LATA;
typedef struct
{
  unsigned LATA0:1;
  unsigned LATA1:1;
  unsigned LATA2:1;
  unsigned LATA3:1;
  unsigned LATA4:1;
  unsigned :2;
  unsigned LATA7:1;
  unsigned LATA8:1;
  unsigned LATA9:1;
  unsigned LATA10:1;
} LATABITS;
extern volatile LATABITS LATAbits;

The problem is, I don't have the linker file contained in my project, so therefore logiscope misses it and suggests all the extern variables should be static.
How can get around this?

Matthew Shearer
Registers are typically not allocated by the program at all, as they sit in the hardware itself. Declaring a register as a value, rather than accessing it through a pointer seems to be the problem here.

For register definitions, you need to deviate from rule 8.10, it simply isn't practical to hide register maps inside private encapsulation, as the rule enforces. For upcoming releases of MISRA-C, I think register definitions should be named as the only allowed exception to the rule.

---

That being said, I guess the reason you wrote your own file is because MISRA-C 18.4 forbids union? The reasons why they are forbidden are named: padding problems, alignment, endianess, bit-order. Struct bit fields contain all of these problems as well. Omitting the union keyword solves nothing if one resorts to bit fields.

Although bit fields are allowed by MISRA-C, they are completely unportable and leads to random behavior of the program if it is ever ported. They might very well lead to random behavior on your current MCU as well. (Allowing bit fields is, in my opinion, one of the biggest flaws of the MISRA-C standard.)

You can however easily solve all of these problems, including your static linkage issue, while at the same time making the program portable to any processor and compiler in the world. Use the following syntax instead:

#define TRISA ( *((volatile uint16_t*)0x1234) ) /* where 0x1234 is the address of the register */

TRISA |= 0x01; /* set bit 0 ti value 1 */
TRISA &= (uint8_t)~0x01; /* set bit 0 to value 0*/

This code will work perfectly even if you have a linker-specific register map elsewhere in the project.

But if you aren't using this syntax, you must write a thick essay of all implementation-defined behavior asociated with bit fields: how your compiler treats struct padding, how your compiler treats the bit padding you are using, whether there is memory alignment on the MCU, how little endian works on PICs, what bit order your compiler uses, how your bit fields will or won't be affected by implicit type conversions, and so on. If you don't write such an essay, your code does not conform to MISRA-C.

Or alternatively, you can use the macro syntax above, then you don't need to document a thing.
thanks Lundin,

Very useful reply.
using the method you've suggested creates an awfull lot of work, but in the long run will probably be well worth it.

thanks again,

Matt
It is common for organisations to raise deviations against Rule 18.4, thereby allowing the use of unions, when including header files that declare machine registers and/or access hardware.

If you choose not to raise a deviation then there are other solutions, including the one suggested by Lundin.

It is possible that your tool is flagging a violation of Rule 8.10 because it does not know about the external definitions of the objects declared in your header file. You could provide stub definitions to your tool in order to provide it with the missing information.

Alternatively your tool may have a flag that you can use to tell it that it does not have full visibility of the project.