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.

MSP430 bit accessing

Other Parts Discussed in Thread: MSP430G2553, MSP430F2418

Hi,

I am using code compiler for my development purpose . When I try to access the bit property of this contrroller , I always get an error . One of the program I am attaching here for your reference . This program I have taken from some sample code , in the code they have asked to use header file as "<io430x11x1.h>" but I am not able to find that file in the directry. Some article says  <io430x11x1.h> is for IAR . However I tried with both the compiler and gets the same error . The error is pasted below the code .Please help me to resolve this

#include

<MSP430G2553.h>

#define

LED1 BIT0

#define

LED2 BIT6

void

main()

{

WDTCTL =  WDTPW | WDTHOLD;

P1DIR = LED1 | LED2;

//TACTL = 0X02E0;

TACTL = MC_2|ID_3|TASSEL_2|TACLR;

for (;;)

{

// Loop forever

while (TACTL_bit.TAIFG == 0) ;

// doing nothing

TACTL_bit.TAIFG = 0;

// Clear overflow flag

P2OUT ˆ= LED1|LED2;

// Toggle LEDs

}

}

Description Resource Path Location Type
#66 expected a ";" main.c /led line 15 C/C++ Problem
#135 expected a field name main.c /led line 12 C/C++ Problem
#20 identifier "TACTL_bit" is undefined main.c /led line 12 C/C++ Problem
#7 unrecognized token main.c /led line 15 C/C++ Problem
#135 expected a field name main.c /led line 14 C/C++ Problem

  • Hi Sikesh!

    I don't know how the header files are managed in IAR, but for CCS there is one header-file for every processor. So if you use a MSP430G2553, you will

    #include "msp430g2553.h"

    and if you use a MSP430F2418, you will

    #include "msp430f2418.h"

    and so on. This "<io430x11x1.h>" does not look like a valid header file for me. If IAR uses this type of naming, then sorry, I didn't know. And which processor are you actually using at the moment? In your program you include the header for the G2553, but this doesn't match with the io430x11x1.h file.

    Now let's have a look at your code:

    #include "msp430g2553.h"
    
    #define LED1 BIT0
    #define LED2 BIT6
    
    void main( void )
    {
      WDTCTL =  WDTPW | WDTHOLD;
    
      P1DIR = LED1 | LED2;
    
      //TACTL = 0X02E0; <- Don't use this cryptic style of setting registers
    
      TACTL = MC_2 | ID_3 | TASSEL_2 | TACLR;
    
      for( ;; )                               // Loop forever
      {
        while( !(TACTL & TAIFG) );            // doing nothing
    
        TACTL &= ~TAIFG;                      // Clear overflow flag
    
        P1OUT ˆ= LED1 | LED2;                 // Toggle LEDs
      }
    }

    I don't know if the code you have posted looks the same in your IDE or if it was disrupted that way when you inserted it. The errors you have posted do not help much, because the line numbers they are referring to are not present.

    Dennis

  • hi ,
    thanks for your reply . I was going through some of the article which explains how to access timerA in MSP430. In one of the article they were monitoring the Timer over flow flag TAIFG with the instruciton " while(TACTL_bit.TAIFG == 0) and clears it with the instruction " TACTL_bit.TAIFG = 0;" . When I tried to impliment it in my code , I was getting an error " undefined symbol" , but in the same article they have used an header file <io430x11x1.h>. ( Yes you are right - This is not a specific name and we need to edit "x"s in the <io430x11x1.h> to have the controller name.

    Can you please also tell me how to access a specific port pin .This is another example I got for bit accessing . But I am getting the same error for bit accessing .

    #include <io430x11x1.h> // Specific device , new format header -- >>> device needs to be specified here
    // Pins for LED and button
    #define LED1 P2OUT_bit.P2OUT_3
    #define B1 P2IN_bit.P2IN_1
    void main (void)
    {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    LED1 = 1; // Preload LED1 off (active low!)
    P2DIR_bit.P2DIR_3 = 1; // Set pin with LED1 to output
    for (;;) { // Loop forever
    while (B1 != 0) { // Loop while button up
    } // (active low) doing nothing
    // actions to be taken when button is pressed
    LED1 = 0; // Turn LED1 on (active low!)
    while (B1 == 0) { // Loop while button down
    } // (active low) doing nothing
    // actions to be taken when button is released
    LED1 = 1; // Turn LED1 off (active low!)
    }
    }
  • Sikesh,

    please insert code using the syntax highlighter. Look at my code snippet and compare it to your one - which is easier to read? :-)

    You find it here:

    and then this small symbol:

    Then this window opens where you can place your code in:

    Then the code gets line numbers and looks better which then results in easier reading. OK?

    Here is your code again:

    #include <io430x11x1.h> // Specific device , new format header -- >>> device needs to be specified here
    
    // Pins for LED and button
    #define LED1 P2OUT_bit.P2OUT_3
    #define B1   P2IN_bit.P2IN_1
    
    void main( void )
    {
      WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
      
      LED1 = 1;                 // Preload LED1 off (active low!)
      P2DIR_bit.P2DIR_3 = 1;    // Set pin with LED1 to output
    
      for( ;; ) // Loop forever
      {
        while( B1 != 0 )        // Loop while button up - (active low) doing nothing
        {
        }
    
        // actions to be taken when button is pressed
        
        LED1 = 0;               // Turn LED1 on (active low!)
    
        while( B1 == 0 )        // Loop while button down - (active low) doing nothing
        {
        }
    
        // actions to be taken when button is released
    
        LED1 = 1;               // Turn LED1 off (active low!)
      }
    }

    You will get the error because things like P2DIR_bit.P2DIR_3 are not known. And I have never worked with it, either. So I won't use it. I would do it that way:

    #include "right_header_file.h" // Specific device , new format header -- >>> device needs to be specified here
    
    // Pins for LED and button
    #define LED_ON     P2OUT &= ~0x08; // Set P1.3 low (active low)
    #define LED_OFF    P2OUT |=  0x08; // Set P1.3 high (active low)
    #define B1_PRESSED !(P2IN & 0x01)  // Button on P2.1 pressed (pulls to GND)
    
    void main( void )
    {
      WDTCTL = WDTPW | WDTHOLD;        // Stop watchdog timer
      
      P2OUT |= 0x08;                   // Preload LED1 off (active low!)
      P2DIR |= 0x08;                   // Set pin with LED1 to output
    
      // If there is no external pull-up resistor, then you have to enable the internal one
      P2REN |= 0x01;                   // Enable resistor
      P2OUT |= 0x01;                   // Set resistor to pull-up
      // End of resistor configuration
    
      for( ;; ) // Loop forever
      {
        if( B1_PRESSED )
        {
          LED_OFF;
        }
        else
        {
          LED_ON;
        }
      }
    }

    Dennis

  • Sikesh Karunan said:

    I am using code compiler for my development purpose . When I try to access the bit property of this contrroller , I always get an error . One of the program I am attaching here for your reference . This program I have taken from some sample code , in the code they have asked to use header file as "<io430x11x1.h>" but I am not able to find that file in the directry. Some article says  <io430x11x1.h> is for IAR . However I tried with both the compiler and gets the same error . The error is pasted below the code .Please help me to resolve this

    Hi,

    The IAR tools provide two sets of IO header files. The ones named mspNNN.h use the traditional Ti-style declarations where each peripheral is an integer and each field is a preprocessor macro defined as a bitmask. The ioNNN.h header files, in the other hand, use a more modern approach. Here, each peripheral unit is defined using a union of an integer (that corresponds to the full register) and a bitfield struct that corresponds to the individual fields.

    For example, TACTL_bit.TAIFG == 0 mean the TAIFG bit of TACTL.

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

  • IAR auto-insert he correct ioxxx.h based on the msp430 device you select in General Options/Target pull-down menu list.
    So to use <msp430.h> or <io430.h> is the only thing you have to worry about, the io430.h is the bit field version.

    P2DIR_3 is not valid, as soon as you type the . you will set the options available and they are P0 to P7
    example: P2DIR_bit.P3 = 1; // set as output.

    If you use #define, don't mix in the msp430.h way of doing it with proper io430.h way.

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/412968/1466911#1466911

  • Tony Philipsson said:

    P2DIR_3 is not valid, as soon as you type the . you will set the options available and they are P0 to P7
    example: P2DIR_bit.P3 = 1; // set as output.

     Hi Tony, from time I switched to MSP430 long time ago I learned to avoid this way of bit access and also avoid as much as possible 8 bit data access too.

     MSP is a 16BIT processor and is more efficient handling a complete 16bit data than accessing single bit one at time: if not assembly optimized 8 bit data load as integer then exchange between registers.

     When I need to do fast processing I only use integers and long integers avoiding Byte and chars.

     Also procedure parameter passing work on word than bytes and passing two bytes result in passing two integer with conversion data in between, return of data is same...

     This was a great hint in speeding code and reducing produced code so I relegated byte access just to string and when low free ram was an issue, I never got this limit and both ram and flash never went to critical sizes. The largest code I wrote was leaving enough space in flash to accomodate another image for upgrade on field over protocol... That time MSP430X was just a rumour for the future.

     SOme trick like using DMA and MAC unit to do prefiltering of ADC data without intervenction of cpu also raise capability of this technological  jewel.

     Very fast interrupt response and other great feature of this processor where hard to beat also from 32 bit arena, maybe new cortex M0+ can do something better but we have to see if really this is true.

  • > from time I switched to MSP430 long time ago I learned to avoid this way of bit access and also avoid as much as possible 8 bit data access too.

    MSP430 have bit,bis.and bic (unlike some other mcu) that also comes in 8bit .b version that the IAR compiler will use properly and many msp registers are 8bit only.
    The complier will notice if a few bit changes in a row have the same destination register and will merge them in to one instruction.
    So set optimization to med or high and look at the tight code IAR makes.

    bitfield's also makes great general boolen flags that don't waste a whole byte.

    So I will use io430.h from now on.

  • Tony Philipsson said:

    > from time I switched to MSP430 long time ago I learned to avoid this way of bit access and also avoid as much as possible 8 bit data access too.

    MSP430 have bit,bis.and bic (unlike some other mcu) that also comes in 8bit .b version that the IAR compiler will use properly and many msp registers are 8bit only.
    The complier will notice if a few bit changes in a row have the same destination register and will merge them in to one instruction.
    So set optimization to med or high and look at the tight code IAR makes.

    bitfield's also makes great general boolen flags that don't waste a whole byte.

    So I will use io430.h from now on

      Hi Tony, I agree what you mean about efficiency but I disagree in another way to try explain what is different.

     Old processors like Z80 carried some special bit manipulation instruction where one can set test reset one bit across one byte of data. Old processor where provided in a similar manner of special bit set reset instruction, I remember something similar on Motorola 68xx series, this is a good idea to avoid load to accumulator then use logical instruction and store back to memory.

     When 68000 was released (and MSP is more close to this than old processors) also some minicomputer can do direct memory operation so can direct execute instruction between two memory location. Array manipulation and (MULTI)bit manipulation was added, code was more short and efficient. 68K series was a 32Bit processor with instruction size 16 bit, MSP is a 16bit instruction and data processing. so is more close to 68K than parallelism and orthogonal instruction. Is just missing the Addressing registers so powerful on array and bit manipulation too.

     When era of RISC come up where MSP belong too some CISC instruction where drop away, so processor core where semplified a lot.

     Successor of early 680xx where xx >=20 where able to manipulate bit field too, so if you your desire was to set reset or apply a pattern was possible on bit specified area, processor was optimizing memory accesses to apply bit operation in 32bit chunk.

     This is again true on MSP430, bit operation can modify not just one bit but all bit of operand size, one bit at a time cannot be combined by compiler optimizers.

     Scenario:

     Program using bit field, this is fine in low end processor like pic avr, this is wrong on MSP or high end processors also if using BIT BANDING...

      Compiler cannot do nothing and instruction get executed one at time.

     COmpiler can optimize multiple bit belonging to same memory location?

     Yes and no:

     I am setting two bit at same time, this is correct and it is wrong set by bit field.

     I am setting bit field one at time but this must be the operation to not overlap single I/O lines:

     first operation is better handled using bit mask that is impossible or cumbersome to use on bit field.

     Second operation is of no difference but if you give the compiler high optimization level and this can group bit field operation together the behaviour of bit pattern change in time, no more bit instruction time is between bit set/reset but all chenge at same time.

     MSP is not accumulator oriented and has a fully orthogonal instruction with some extension, code can be executed also out of order due to optimization...

     MSP432 is now released too, I am as all of us than TI employee at begin of learning curve but inferring what I learned from TIVA and now from Cortex competitor this is a high end processor core, instruction are pipelined and worst usage of bit field can generate unexpected behavriour more worst of MSP related so my point of view is to avoid BIT field on these classes of processors if you are not just using as hobby processor.

     Happy to share again point of view about this, I remember old JMG conversation now insterspersed in a lot of request about how to add two numbers....

  • if you use a var through a bitfield the compiler knows to treat it as a 0 or 1 boolen.
    P1OUT_bit.P2 = P1IN_bit.P3 is perfectly OK
    (P1OUT & BIT2) = (P1IN & BIT3) would NOT work.

    You could fix that with:
    (P1IN & BIT3) ? (P1OUT | BIT2) : ( P1OUT & ~BIT2)
    The bitfield version above using optimization ends up doing that in the resulting machine-code.

    If the compiler bunch together bit banging bits but you're doing your own data/clk system, there is #pragma optimize=3 z

    On ARM with its use of bit-banding to access bits in a single atomically instruction,
    would it help the compiler to do that all the time if it's a bitfield variable?

    Is bitfeild and io430.h getting deprecated (phased-out) or is it being more acceptable?
    As io430 still can be used as the same was as you would with mp430.h, and don't see why not make it the default(?)

  • Tony Philipsson said:
    if you use a var through a bitfield the compiler knows to treat it as a 0 or 1 boolen.
    P1OUT_bit.P2 = P1IN_bit.P3 is perfectly OK

     Right and compiler optimize as necessary single atomic boolean operation too.

    Tony Philipsson said:
    (P1OUT & BIT2) = (P1IN & BIT3) would NOT work.

     Ouch,,,

     This is a worst code, P1IN and P1OUT are separate register and P1OUT is read write P1IN is read only.

     So P1OUT & BIT2 generate forever a bitwise logic operation result and never can be assigned to nothing. It make result zero or 4 (BIT2) depending on bit status.

     P1IN & BIT3 is incompatible in value with OUT generated one of zero or 8 (BIT3) also number are incompatible and this is not a logic operation so:

     C Operator:

     Logic

     A,B,C  are variable carrying value of zero is false true otherwise value is non zero.

     C= !A; //  is  Boolean not, False if variable is zero True if non zero result are 0 or 1 (-1 0xffff) depending on compiler implementation.

    C= A || B ; Logical  Or between TRUE FALSE so C carry boolean result zero if both var are false, true if one or both are non zero.

    C = A && B; // Logical AND boolean result is zero if one or both var are zero, true if both var are non zero.

    Bitwise logical operation:

    C= ~A; // C contain bit to bit logic not and value is 1 complement of variable A, destination and source must be same size.

    C= A&B; // bitwise and between variables, result is zero if var don't have ones in same bit position. Different from zero if both have bit set to one and value set to a value to be calculated not simply true or false.

    C= A& B; // is bit to bit or of both var result is a value where one is present where ones are on original bit positions.

     -------------------------------------

     Example:

     A= 0x16; B= 0x11;

    A&&B  give bool result TRUE

    A&B give result  0x10 (bitwise And) still true but not boolean true

    A||B give result TRUE (Maybe 1 or -1)

    A|B give result =x17 (bitwise or)

    A= 0x30; B= 0x03;

    A&&B give bool result TRUE

    A&B Give result 0x0 -> FALSE

     

    Tony Philipsson said:
    On ARM with its use of bit-banding to access bits in a single atomically instruction,
    would it help the compiler to do that all the time if it's a bitfield variable?

     Sorry I don't know so in deep ARM, I was proud in old 1987 to demonstrate ARM was inferior to 68000 code but not now I am using ARM from C as is. My preferred RISC architectures was 88000 able to responf to interrupt in just one clock cycle. Time elapsed ant that ultrafast power horse got rest house as for PARISC powerPC as RS/6000 too.

     ARM I just learnt has saturating math instruction as MAC necessary to perform efficient DSP algorithm.

    Tony Philipsson said:
    Is bitfeild and io430.h getting deprecated (phased-out) or is it being more acceptable?

     Is acceptable Tony, just remember MSP only access  WORD memory so care about real code execution.

    P1OUT_bit.P2 =non zero; can be translated as

    P1OUT|=BIT2; and this is an atomic 16 bit instruction if non zero is a constant but can also be translated in more than one instruction if non zero come from a variable.

    P1OUT_bit.P2 = P1IN_bit.P3 is non atomic and generate more than one assembly instruction.

  • On the msp430 all the instructions is also available as 8bit versions, so I would not say you need to think in a 16bit way all the time.
    And bitfields can occupy a word as they are not limited to a byte, they are not even limited to a single bit but can you mix 1, 2bit and nibbles etc.

    Only on the ARM could you copy the state of one bit to another bit in one single atomic write.
    example: mov  0x2002, 0x200A // these are not real addresses but bits in the ram 0x200 and 0x201 locations.
    But back to the msp430, below you can see the complier knows what to do and the destination is not read-modify-write.

     P1OUT_bit.P2 = P1IN_bit.P3;         // BIT FIELD VERSION
      
      if (P1IN & BIT3)                   // AND + OR version
        P1OUT |= BIT2;
      else 
        P1OUT &= ~BIT2; 
    
    Compiles to exactly the same code:
    
    
     00C09C    B2F2 0020          bit.b   #0x8,&P1IN
     00C0A0    2C03               jc      0xC0A8
     00C0A2    C2E2 0021          bic.b   #0x4,&P1OUT
     00C0A6    3C02               jmp     0xC0AC
     00C0A8    D2E2 0021          bis.b   #0x4,&P1OUT
     00C0AC    ...
     
  •  Hi Toni, I am not able to find where I read tips about programming, but refer page 24 of userg guide, http://www.ti.com/lit/pdf/slau144  

    here you can see between peripheral and CPU/Memory data bus there is an 8 bit bus adapter. So byte access here is just limited to byte, on memory is different and I point you to programming tips asap I found again or I browse early cd was on old good paralel FET kit.

  • The discussion about the bitfield versions of the control registers has been done several times in the past.
    Using bitfields is convenient. Yes. No question.
    And it is inefficient.
    For a single isolated bit operation, there is usually no difference.
    But if you use such a definition to set and clear all bits of a control register, each bitfield access ends up in a separate RMW instruction, And if a parameter is larger than one bit, things become even worse.
    Since the hardware registers are volatile, the compiler cannot optimize the access.
    If you directly use the binary operators to construct the value, it is (worst case) an AND and then an OR instruction.
    Also, reading or writing a register can have side-effects that are not obvious by the code when using bitfields.
    The only thing that's worse than using bitfields is to call a library to manipulate register bits (like 'set_IO_pin_to_module_usage(port, pin)') Especially if they are real functions and no macros.

    Tony, you're right, it usually makes no difference doing a 16 bit or an 8 bit access on an MSP. Unless the module requires a certain access (like 20 bit access for DMA address registers and 16 bit accesses to DMA control registers)
    Doing two 8 bit accesses for a 16 bit operation is waste of time, unless you don't know whether the 16 bit value is word-aligned, since the MSP silently ignores the LSB of the address on .W or .A instructions.

    The P1.2=P1.3 example could be also done like this:
    P1OUT=(P1OUT&BIT2)|(P2IN&BIT3)>>1;
    Well, it's same size and requires two registers. but if the members are larger than 1 bit, this version might be shorter.

    There's a reason why the bitfields have been removed from the header files of MSPGCC and CCS years ago.
    After all, microcontroller coding is about maximum program efficiency, not about maximum coder convenience.
  • >all, microcontroller coding is about maximum program efficiency,
     

    But I expect a compiler running on a 4GHz computer to know what is best and have a solution for all possible bit lengths.
    Though even IAR shows that they are not there yet.

    If it's one bit moved to another bit solution: bitest, jnc, bis or bic

    if a nibble: (atomic write to final destination is a must, but a IRQ should not write the same register incase IRQ happens midpoint on the last line )
    mov source to R12,  rla if needed, and w/bitmask.
    mov dest to R13, bitclear R13 w/ bitmask, bitset R12,R13, mov R13 to dest

  • You forget about side-effects. The compiler doesn't know that reading a register will auto-clear some bits or other such things that may happen. Only the coder knows (or at least should know).
    Things that are done automatically, can go automatically wrong.

    For normal structures and variables, all this is no problem. And the compiler can and will handle them efficiently, even grouping multiple accesses, combining shifts, whatever. The compilers are doing a really good job here.
    But when it comes to hardware registers, things are different. Each register may require a specific handling. Something the compiler has no database for. (and can't).
    So the compiler is limited to safest strategy. Sometimes, this is efficient, sometimes it is not.
    (in the bit move example, if your source or destination bit is determined by a variable index, you can't use bitfields not at all anyway. Something you could do with those CPUs with bit addressing.)

    Give a user a library and he will expect things from it that it can't do, just by not knowing of (or caring for) the inner workings.
    (I guess, the I2C library code has caused more trouble than it saved) Same for bitfields on hardware registers. Those who know how to safely handle them do not need them.
    Try to put a bitfield over the watchdog register or any other password-protected register. You will never get it running.
    And then explain the user why for some registers there are bitfields, for others aren't. He will keep asking and complaining, filing bug reports etc.

**Attention** This is a public forum