This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Union boolen bit structure for Port Register

This seems to work pretty well with IAR (set optimizations to high)
Unlike #define Button (P1IN & BIT3) this actually returns a boolen value 0 or 1

You can not mix your code with regular P1IN and P1OUT as it complains about overlap.
Could not get #undef to work to actually over write the original P1IN (it uses DEFC() and is there a UNDEFC()?)
Would like to just use PIN and POUT name for all Ports (P1, P2,P3), e.g a 24bit field uses 3 byte destinations that are not back to back (possible?)
 optional, you could omit the PIN1 name in the structure (anonymous) and then only directly refer to the bitname REDLED = BUTTON;

__no_init volatile union{
  struct{ unsigned char
    IN_0         : 1,
    IN_1         : 1,
    IN_2         : 1,
    BUTTON       : 1,
    IN_4         : 1,
    IN_5         : 1,
    IN_6         : 1,
    IN_7         : 1;
  } PIN1; } @ P1IN_;

__no_init volatile union{
  struct{ unsigned char
    REDLED       : 1,
    OUT_1        : 1,
    OUT_2        : 1,
    OUT_3        : 1,
    OUT_4        : 1,
    OUT_5        : 1,
    GREENLED     : 1,
    OUT_7        : 1;
  } POUT1; } @ P1OUT_;

 int __low_level_init(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  POUT1.REDLED = PIN1.BUTTON;  //<< EXAMPLE
  return PIN1.BUTTON ;      //<< EXAMPLE
}

  • Hi,

    I saw that you are modelling the peripheral units using a bitfield struct.

    I just wanted to point out that the IAR tools comes with two sets of IO header files. The first, mspNNN.h use the traditional integer approach. The second, ioNNN.h model all registers using a combination of unions and bit field structs. For example, the P1IN register looks like:

    __no_init volatile union
    {
      unsigned __READ char P1IN;   /* Port 1 Input */
    
      struct
      {
        unsigned __READ char P0              : 1; /*  */
        unsigned __READ char P1              : 1; /*  */
        unsigned __READ char P2              : 1; /*  */
        unsigned __READ char P3              : 1; /*  */
        unsigned __READ char P4              : 1; /*  */
        unsigned __READ char P5              : 1; /*  */
        unsigned __READ char P6              : 1; /*  */
        unsigned __READ char P7              : 1; /*  */
      }P1IN_bit;
    } @0x0020;
    

    In other words, the symbol P1IN refer to the full register whereas P1IN_bin.P4 refers to a specific bit.

    In other registers, the bits have more symbolic names.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • Thanks that is something new I learned, replacing the msp430.h with io430.h.
    Though you theoretically could edit the io430 file to change P0 to REDLED,
    using define is probably more acceptable, plus it gives me the option to name all ports just P.
    Though I miss getting the hint of possible field names of the structure to use when typing.

    #include <io430.h>  // bit field version
    #define POUT_REDLED P1OUT_bit.P0
    #define PIN_BUTTON P1IN_bit.P3

    POUT_REDLED = PIN_BUTTON;

    P.S. In med/high-optimization why does it compile to where the first line is mov.b &P1IN,R14, but it's never used?
    R14 is used when no/low optimizations, so it looks it's left behind trash. 

  • Tony Philipsson said:

    P.S. In med/high-optimization why does it compile to where the first line is mov.b &P1IN,R14, but it's never used?

    R14 is used when no/low optimizations, so it looks it's left behind trash. 

    This is because P1IN is declared "volatile". The compiler must ensure that all accesses to volatile variables are preserved, so we're not allowed to remove the instruction even if the value isn't used.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • "Unlike #define Button (P1IN & BIT3) this actually returns a boolen value 0 or 1"

    Well, boolean is not binary. Boolean (as C defines it) is zero (false) or non-zero (true)
    Also, usually, 'true' is declared as -1, which is only '1' in case of a single-bit variable size. (true for a bit field)
    using the above define,
    "if(Button)..." does exactly what you want.

    Using a bitfield actually forces the processor to do an additional shift operation. This would be equivalent to
    #define Button ((P1IN&BIT3)>>3)
    Since the CPU has explicit instruction for branching on zero or not zero (bit not on BIT3), using the original Button define the proper way (not comparing it against a value) is the more efficient way.

    Using bit fields on hardware registers is inefficient in other means too. The compiler cannot optimize access to hardware registers (and must not), so using bit fields, you are forcing the compiler to generate less effective code where you (knowing the purpose of your code and the functionality of the register) could write a way more efficient formula by hand, using normal bit operators. And on MCUs, efficiency should come long before convenience.

**Attention** This is a public forum