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.

SPI UCBUSY problem

Other Parts Discussed in Thread: MSP430FR5969, MSP430FR5739

Hello,

I am using MSP430FR5969 and I have problem while setting up SPI on eUSCI A1 to communicate with H3LIS331DL accelerometer. It works flawlessly on eUSCI B0 but it will be used for RF module.  As soon as I connect accelerometer to SPI, program gets stuck on while (UCA1STATW & UCBUSY);. This happens only when I try to read two bytes without releasing chip select pin. Logic analyser shows that everything is ok, values sent and received are ok, but microcontroller stuck thinking that the operation is in progress. When I disconnect accelerometer this problem disappear but only after MCU reset. I tried to change almost everything in SPI config registers, tried all combinations of reading and writing SPI buffer and no effect. It always gets stuck on UCBUSY.

Simplified code follows:

 

                             // Configure GPIO

                             P4DIR |= BIT3;                                                                                         // CS pin

                             P4OUT |= BIT3;

 

                             P2SEL1 |= BIT5 | BIT6 |BIT4;                                                                 // USCI_A1 operation

 

                             // Configure USCI_A1 for SPI operation

                             UCA1CTLW0 = UCSWRST;                                                                       // **Put state machine in reset**

                             UCA1CTLW0 |= UCMST | UCSYNC | UCCKPL | UCMSB;                    // 4-pin, 8-bit SPI master

                                                                                                                                               // Clock polarity high, MSB

                             UCA1CTLW0 |= UCSSEL__SMCLK;                                                        // ACLK

                             UCA1BR0 = 0x02;                                                                                    // /2

                             UCA1BR1 = 0;                                                                                           //

                             UCA1MCTLW = 0;                                                                                    // No modulation

                             UCA1CTLW0 &= ~UCSWRST;                                                                 // **Initialize USCI state machine**

 

 

 

                             P4OUT&= ~BIT3;

                             while (!(UCA1IFG & UCTXIFG));

                             UCA1TXBUF = (READ_REG + WHO_AM_I);

                             while(!(UCA1IFG & UCRXIFG));

                             value = UCA1RXBUF;

                             while (!(UCA1IFG & UCTXIFG));

                             UCA1TXBUF = 0x00;

                             while(!(UCA1IFG & UCRXIFG));

                             value = UCA1RXBUF;

                             while (UCA1STATW & UCBUSY);  <- stuck here

                             P4OUT|= BIT3;

  • In SPI master mode, there is only one reason why UCBUSY never gets clear: you don’t have a clock. However, without a clock, you should never make it so far, as you’re waiting for UCRXIFG, which can’t be set without a clock. So I don’t know what’s going on, it makes no sense. Well, I haven’t used the eUSCI myself so far.

    One thing: you should set PxOUT before setting PxDIR. Currently, id PxOUT is initially 0, you’ll get a short low pulse on your CS signal that may confuse the slave.

  • Don't eUSI have a IRQ for UCBUSY? (or as serialized-data transfer complete IRQ)

    Maybe your routine in not getting stuck in while(),
    it's it getting stuck in a endless IRQ serviced over and over as you don't clear IFG flag etc?
    So check your IV table etc.

    And maybe even start using the ucbusy irq.
    My code is NEVER allowed to use while() out of power consumption and multitasking principle.

  • Tony Philipsson said:
    Don't eUSI have a IRQ for UCBUSY?

    No, it hasn’t. It has a clock low timeout interrupt. And a byte count zero interrupt (and can automatically send a stop if byte count is reached, allowing to receive a single byte without busy-waiting)

    However, busy is set when a start condition is detected, including one that is generated by the USCI itself. It is cleared by receiving a stop, including a self-generated. An interrupt on it wouldn’t make much sense.

  • With MSP430FR5739 and ST LIS2DH accelerometer, the following code for SPI B0 (SPI clock 2MHz or 4MHz) works fine in my projects.

       P1OUT &= ~BIT5;     // GSensor selected
       UCB0TXBUF = gs_xyz_r_addr;
       while ((UCB0STATW & UCBUSY));    // SPI B0 Buffer Ready?
       gs_xyz_r_buff[0] = UCB0RXBUF;
       UCB0TXBUF = 0;          // Read Value from the sent Address
       while ((UCB0STATW & UCBUSY));    // SPI B0 Buffer Ready?
       gs_xyz_r_buff[1] = UCB0RXBUF;
       UCB0TXBUF = 0;          // Read Value from the sent Address
       while ((UCB0STATW & UCBUSY));    // SPI B0 Buffer Ready?
       gs_xyz_r_buff[2] = UCB0RXBUF;
       P1OUT |= BIT5;

  • I know this is old but I really struggled with a similar problem and thought I would share. With the FR5969, running an SPI Master with the MCLK@ 16 MHz and BRCLK @ 4 MHZ, there appears to be a race condition testing UCBUSY.  Unless you are polling you would probably never see it. But with the SPI running this fast, waiting for an IRQ hardly seems useful. In this configuration UCBUSY clearly gets stuck on very rare occasions for no good reason. If you wait for it infinitely, the code will hang. 

    My solution is simple but non-obvious, use UCRXIFG as the wait condition, even for transmit operations. This works well since all TX operations inherently create an RX operation, and the RXIFG is the last event to occur. Once it occurs, you can clear it and be confident that the next TX operation will not hang. The cost is half of a BRCLK, but it seems to be the only thing that works reliably. 

  • When waiting for RXIFG, depending on phase and SPI clock ratio, TX might still be not complete.
    I really don't see why a TX operation will hang: if the MSP is master, TX will always complete, and once done (and RX done), UCBUSY will clear.

    You're right, with high BRCLK, using interrupts makes no sense. I sometimes use DMA (for 512 bytes block transfers from/to SD-card), else I use carefully crafted code, so one code loop exactly takes 8 MCLK/BRCLK cycles, so I don't need to check for TXIFG at all.

    Implementing an SPI master is the easiest thing of all synchronous transfers. If it hangs, then there is some quirk in the top-level code or the top-level protocol.

    Some addition to the eUSCI and interrupts: in SPI mode, there are only RXIFG and TXIFG. Clock low and byte count are only available in I2C mode. Too bad. BUSY and Bus conflict interrupts would have been very nice. So for SPI, the eUSCI has no enhancements. Worse, on some eUSCI devices, DMA does not work reliably. :(
  • Agreed: "Implementing an SPI master is the easiest thing of all synchronous transfers. " At least it should be, but on this part and at this speed, in reality, it does not work as expected. There is a quirk, but I am pretty sure it is in the eUSCI. That may in fact be why the DMA fails as well. 

    My workaround is proven, after hours of trying other ways. It should probably be in the errata. 

  • To Mike and to the original poster,

    I can confirm the UCBUSY problem exists on FR5969 running at 16MHz with a 1MHz SPI clock.    Here's my SPI transfer code:

    uint8_t spiTransfer(const uint8_t value) {
    
      UCA1TXBUF = value;
    
      while (UCA1STATW & UCBUSY);
    
      return UCA1RXBUF; // reading clears RXIFG flag
    
    }

    And here's a timing diagram showing what should be 10 successive calls to my spiTransfer() routine.   As you can see, after the 4th and the 9th call, it hangs waiting for the UCBUSY bit to clear.   What puzzled me is that consistently after about 1ms, the condition is satisfied for some reason and transfers continue.  

    Many thanks to Mike for posting his reply and suggesting to use UCRXIFG as the end condition (which I tested and verified works), otherwise I would likely still be puzzling over this.

  • Just a quick followup:
    I religiously read the errata for any new chip I am working with, and the errata for the MSP430FR5969 dated April 2015 doesn't list this issue, but the recent October 2015 errata does, as errata number USCI41, surely due to Mike's findings. Thanks again.
  • Glad I could help :-)

**Attention** This is a public forum