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.

Checking one bit only of IFG2

I am working on a project that uses a UART on USCI_A0 and SPI on USCI_B0.  The UART functioned perfectly before the SPI interface was implemented.  Now it sends on or two bytes out of the UART and then gets stuck in the following line of code:

while (!(IFG2&UCA0TXIFG));            // USCI_A0 TX buffer ready?

because the UCB0TXIFG and UCB0RXIFG are at bits 2 and 3 of the IFG2 and UCA0TXIFG is BIT0 of IFG2 if any of these other bits are high it will get stuck in the line of code above.  Does anyone have any ideas on how to fix this?


Thanks,

Corin

  • Corin Browning said:
    if any of these other bits are high it will get stuck in the line of code above

    Are you sure about that? "&" is a bit-wise AND operation. First off, UCA0TXIFG = BIT1, not BIT0 (Assuming 2xxx device, since you don't specify).

    So the outcome of the IFG2&UCA0TXIFG portion is either 0x00 (FALSE) or 0x02 (Not FALSE), so the logical NOT operation should invert that.

    You can see the assembly is

    putc:
    bit.b 0x2,&IFG2
    jnc putc

    That looks correct. And the other bits in the register should not affect how this operates. I think you have something else going on. If it hangs, it's because the bit is never getting set.

  • Sorry about that, mixed up RX and TX flags for UCA0.  Rx is BIT0 tx is BIT1.  And for UCB0 rx is BIT2 and tx is BIT3.  Here is my initialization routine for the UART, maybe somebody can find something that would cause it to conflict with the SPI initialization.

    /**
     * Initializes the UART for 9600 baud with a RX interrupt
     **/
    void initUART(void) {

            P1DIR = BIT0;

            //Sets all the pins on Port 1 to I/O
            P1SEL = 0;
            P1SEL2 = 0;

            //For UART Steps see pg 424
            UCA0CTL1 = UCSWRST;


            //UCSWRST = 1;
            //int i = 0;
            //UCSWRST = 0x00;

            UCA0CTL0 = 0x0;


            UCA0CTL1 |= BIT6+BIT7;    //Take UART out of RESET (toggle 1st bit of UCA0CTL1)
                                        //Select clock source for UART (6th and 7th bit in UCA0CTL1)
                                        // (UCCSEL)  --- 2^7 = 0x80h & 2^0 = 0x01h => 0x81


            //Baud rate settings for 8MHz (9600bps)
            //Refer to table on page 435 in MSP430x2xxx document
            UCA0BR1 = 0x03;        //load UCA0BR with 833(dec)= 0x341h
            UCA0BR0 = 0x41;        //UCA0BR is UCA0BR0 and UCA0BR1 where BR1 is the high byte

            //UCOS16 = 0 and UCBRF0 = 0 and UCBRS0 = 2  UCBR0 = 833 (see table on page 435)
            UCA0MCTL = 0x04;    //Baud rate settings for 8MHz (9600bps)

            //Setting port pins
            P1DIR |= BIT2;

            P1SEL |= BIT2; // Primary peripheral module function is selected.
                              // With the following line commented out (//P1SEL2 = BIT2;)

            P1SEL2 |= BIT2; // Secondary peripheral module function is selected.
                                 // (if P1SEL and P1SEL2 are set high)


            UCA0CTL1 &= (0xFF - UCSWRST);//Clearing RESET bit

            //UCA0CTL1 |= UCSSEL_2; //Select clock source for UART (6th and 7th bit in UCA0CTL1)

            //UCBRS = 0x02;
            //UCA0BRS0
            //UCA0CTL0 = 0x00;
            //UCA0MCTL = 0x00;
            //UCA0TXIE = i;
            //UTXEx = 1;


    }

  • Corin Browning said:
        UCA0CTL1 |= BIT6+BIT7;    //Take UART out of RESET (toggle 1st bit of UCA0CTL1)

    The comment doesn't match the command. This line does NOT take the UART out of reset.
    Besides this, I strongly recommend using the specific defines rather than BITx values. It's really easy to set something completely wrong and never notice.
    UCA0CTL1 |= UCSSEL_3; is much more telling.

    Corin Browning said:
            UCA0CTL1 &= (0xFF - UCSWRST);//Clearing RESET bit

    Don't use arithmetic operations ("-") on bit values.
    The proper, typesafe and much easier to understand notation is
    UCA0CTL1 &= ~UCSWRST;

    You have 8MHz SMCLK? Sure? Because the divider you use sets the USCI up for 9600Bd from 8MHz SMCLK.

    Corin Browning said:
     * Initializes the UART for 9600 baud with a RX interrupt

    I don't see you enabling the RX interrupt (which must be done after clearing SWRST)

  • First off I want to express my gratitude to the TI community for all the help and suggestions, this is my first "major" C code MSP430 project and it's proven to be quite a challenge but the breakthroughs make all the head banging worth it.

    One of the beauties of assembly was that everything was so in depth and you could account for all the registers/memory/PC/stack and manipulating individual bits was very straight forward. I think I've gotten a better handle on bit manipulation in C now, it's just a little more complicated in my opinion.  I've been doing C programming for years but not for uPs. It does seem however that C has an advantage because less lines of code are needed to get what you want done, you just have to make sure you understand what each line is really doing "behind the scenes" so to speak.

    I've managed to get the UART working along with the SPI interface.  I'm still having some strange issues here and there but I am really glad to have both the SPI and UART interface functioning now.  The main challenge from here on is storing 128bits from the SPI buffer into memory (FLASH?) and analyzing that data for finding the header "0000000001" and from there finding the unique 38bit "serial #" contained within those 128bits.  Right now I am having difficulty passing the data in the SPI Rx buffer to a global variable (volatile) and using this data later on, ie to print to the terminal the word/byte the contents of the SPI Rx buffer.  I had read in my MSP430 textbook that the SPI interface can be set to receive 16bits instead of 8 for each segment of the transmitted data.  If only I could figure out how to store 8 words from the SPI into memory...

    Jens-Michael Gross said:

        UCA0CTL1 |= BIT6+BIT7;    //Take UART out of RESET (toggle 1st bit of UCA0CTL1)

    The comment doesn't match the command. This line does NOT take the UART out of reset.
    Besides this, I strongly recommend using the specific defines rather than BITx values. It's really easy to set something completely wrong and never notice.
    UCA0CTL1 |= UCSSEL_3; is much more telling.

    [/quote]

    Thanks, this was a misleading comment, as you saw the software reset bit was cleared later on in the UART_init function.  I would prefer to use mnemonics such as UCSSEL_3 for example but half the time I can't find the proper mnemonic that the compiler recognizes.  I was using CCS and I really liked the ability to press CTRL and click on a mnemonic and go directly to the header/file where it is defined/created, but now I am using IAR (more stable on my current system) and it doesn't seem to have this ability.

    Jens-Michael Gross said:

            UCA0CTL1 &= (0xFF - UCSWRST);//Clearing RESET bit

    Don't use arithmetic operations ("-") on bit values.
    The proper, typesafe and much easier to understand notation is
    UCA0CTL1 &= ~UCSWRST;

    [/quote]

    Thanks I will change this, could you tell me why using arithmetic on bit values is dangerous?  I had seen this method of clearing bits in some code examples.

    Jens-Michael Gross said:
    You have 8MHz SMCLK? Sure? Because the divider you use sets the USCI up for 9600Bd from 8MHz SMCLK.

    The DCO has been calibrated to 8MHz in a CLK_init() function and has been verified to be at 8MHz when measuring the time on the scope to perform an operation and comparing that to the clock cycles taken to perform the operation. 

         * BCSCTL2: Basic Clock System Control 2
         *
         * SELM_0 -- DCOCLK         (main clock [MCLCK] source select)
         * DIVM_0 -- Divide by 1    (Division of MCLCK)
         * ~SELS -- DCOCLK            (source select for subsystem clk [SMCLCK])
         * DIVS_0 -- Divide by 1    (Division for SMCLCK]
         * ~DCOR -- DCO uses internal resistor        (
         *
         * Note: ~<BIT> indicates that <BIT> has value zero
         * PAGE 289 in MSP430x2xxx
         */
        BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;

        //Checking if there is data in DCO Oscillator Calibration Register
        if (CALBC1_8MHZ != 0xFF) {
            /* Follow recommended flow. First, clear all DCOx and MODx bits. Then
             * apply new RSELx values. Finally, apply new DCOx and MODx bit values.
             */
            DCOCTL = 0x00;            //clearing frequency select and modulation selection
            BCSCTL1 = CALBC1_8MHZ;      /* Set DCO to 8MHz */
            DCOCTL = CALDCO_8MHZ;
        }

     * Initializes the UART for 9600 baud with a RX interrupt

    I don't see you enabling the RX interrupt (which must be done after clearing SWRST)

    [/quote]

    There are still a couple misleading comments in my code, sorry about this!  The UART is configured for transmit only for printing to a terminal for debugging purposes.  And the SPI interface is configured for receiving only (the functionality was tested via loopback method: setting the transmit buffer = to the receive buffer) and has been verified to be functional. Thanks to llmars for helping me understand how simple the SPI interface can be to setup.
  • Corin Browning said:
    The main challenge from here on is storing 128bits from the SPI buffer into memory (FLASH?) and analyzing that data for finding the header "0000000001" and from there finding the unique 38bit "serial #" contained within those 128bits. 

    IMHO it's a bad idea to store raw data in flash, as flash writing is slow. YOu probably need to write it to a ram buffer first, or you'll likely miss bytes while a flash write is in progress.
    Even if SPI is slow enough, it would be a better idea to buffer enough in ram so you can realtime-check for the header and store only the already processed data in flash.

    Corin Browning said:
    I would prefer to use mnemonics such as UCSSEL_3 for example but half the time I can't find the proper mnemonic that the compiler recognizes.

    To know which bits to se, you already need to look into the users guide.
    The register description tells that there are bits for the clock selection and they are named UCSSELx. So UCSSEL0 i teh lowest bit, UCSSEL1 the next higher. And for bitfields like this, the header files also define UCSSEL_0..UCSSEL_3 as an enumeration of all possible bit combinations
    UCSSEL_0 = 0
    UCSSEL_1 = UCSSEL0
    UCSSEL_2 = UCSSEL1
    UCSSEL_3 = UCSSSEL0|UCSSEL1

    This nomencalture is used for almost all control bits in all hardware registers (exceptions are e.g. the passwords).

    In addition, there are usually 'telling' defines available, like UCSSEL_ACLK. However, these you need to know (or guess).

    Corin Browning said:
    Thanks I will change this, could you tell me why using arithmetic on bit values is dangerous?  I had seen this method of clearing bits in some code examples.


    To use the above defines:

    UCSSEL0 | UCSSEL0 = UCSSEL0. UCSSEL0+UCSSEL0 = UCSSEL1. Sometimes, defines already inlcude certain bit combination. If you or one of these bits accidentally to the value, it makes no difference,. If you add it, the outcome is something completely different.
    For subtraction, well, if a bit you subtract isn't set in the original value, you'll get something completely different. if you use a peroper &~, the result is the same as if it were.
    Also,
    (0xff-UCSWRST) gives 0xfe. If the register you're working on is a 16 bit register, you'd unintentionally clear the upper 8 bits. ~UCSWRST gives 'all bits set except for UCSWRST', no matter how large the target register is.

    If used correctly, both methods lead to the same results. But if not used correctly by accident or typo, using arithmetic operators almost guarantees an irregular outcome while at the same time obfuscating the problem.

    Using bit operators also makes clear that you're workign with bits here, not with values, making the code mroe obvious to the reader (including yourself, if you look at it again after some time)

**Attention** This is a public forum