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 FR5739 SPI Slave Latency Issues

I am trying to mimic an EEPROM on the MSP430 FR5739 FRAM microcontroller by having the MSP430 act as the SPI slave device (in 4-wire mode).  I have verified that the SPI and the FRAM are working as they should, except that the SPI is not responding quick enough.  What is happening now is that the MSP430 is not getting the instructions from the master quick enough, and thus, making the MSP430 out of sync

I have done this before on a different microcontroller, but I switched to the TI microcontroller because the EEPROM R/W is much faster on this model microcontroller.  However, in the last microcontroller, I was able to speed up the CPU's instruction processing frequency to 32 MHz, whereas I can only bring the instruction processing frequency up to the internal oscillator frequency of 24 MHz.  

Currently, I have an interrupt for the SPI SS pin, the SPI transmit interrupt, and the SPI receive interrupt.  In order to stay consistent with the previous microcontroller functionality, I would like to initiate an interrupt as soon as the SPI receive buffer has received data.  This is how I have the interrupt set up for the receive:

#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
     volatile unsigned int i;

     switch(__even_in_range(UCA0IV,0x04))
     {
          case 0: break; // Vector 0 - no interrupt
          case 2:
               while ((P1IN & SPI_SS) != 0);
               RXData = UCA0RXBUF;
               UCA0IFG &= ~UCRXIFG;
               __bic_SR_register_on_exit(CPUOFF);// Wake up to setup next TX
               break;
          case 4:
               //while ((P1IN & SPI_SS) != 0);
               while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?

               UCA0TXBUF = TXData; // Transmit characters
               UCA0IE &= ~UCTXIE;

               break;
          default: break;
     }
}

I also wish to run it at the code at the same speed as the last microcontroller, which was at 32 MHz.  The good news is that while the last microcontroller had a shared buffer for the send and receive, the MSP430 has two separate buffers.  I am also somewhat familiar with DMA, but I am still unfamiliar with the functionality of the module.  Does anyone out there have any suggestions?

  • dauletle said:
    I also wish to run it at the code at the same speed as the last microcontroller, which was at 32 MHz.

    I wish msp430 run as fast as ARM I am familiar with, or Intel Core i7 - for same price and same consumption msp430 is designed for. But I know that's impossible.

    dauletle said:
    I am also somewhat familiar with DMA, but I am still unfamiliar with the functionality of the module.  Does anyone out there have any suggestions?

    dauletle said:
    I would like to initiate an interrupt as soon as the SPI receive buffer has received data.

    DMA will not help to reduce interrupt latency, it can just improve SPI data transfer speed.

  • Ilmars said:
    I wish msp430 run as fast as ARM I am familiar with, or Intel Core i7 - for same price and same consumption msp430 is designed for. But I know that's impossible.

    That was my mistake for not being clear.  The previous microcontroller was an 8-bit MCU, and (I recall) the internal oscillator speed was set to 8 MHz.  However, the MCU used internal PLLs for fast peripheral clock generation, allowing the instructions to be processed at 32 MHz.

    Ilmars said:
    DMA will not help to reduce interrupt latency, it can just improve SPI data transfer speed.

    Is the DMA able to improve the transfer speed of SPI data coming from the receiver buffer? What I believe is occurring in my implementation is that the master is sending data as fast as possible, and the receive interrupt I've set up is not able to read the data from the receive buffer quick enough.  Therefore, data being sent from the master to the slave MSP430 is getting lost, and thus, my internal state machine are out of sync.  

    I understand that DMA transfers data from one address to another, without CPU intervention (thus making transfers quicker).  So since I haven't found a similar peripheral clock boost in the MSP430, I was wondering if having separate transmit/receive data buffers, as well as implementing DMA, would allow the code written in the MSP430 to be quick enough to work with the master SPI chip.

    If it is possible for the DMA to improve the speed, I would like to know of a good way to set up the DMA for quicker SPI Reads.

    (A bonus that may help speed things up is to use DMA in the EEPROM read and write instructions, but I think I have an idea of how to do that)

     

  • dauletle said:
    Is the DMA able to improve the transfer speed of SPI data coming from the receiver buffer?

    Yes. Because DMA does not execute CPU instructions which takes time (clock cycles) to execute, it just Directly transfer data from Memory using direct Access (DMA).

  • That's great! So from what I understand, if I implement DMA into my code, I can remove the number of clock cycles it takes to read each bit from the SPI Receive Buffer (UCxRXBUF), and thus, only need a single clock cycle to read the UCRXIFG flag indicating that there is data in UCxRXBUF (since reading UCxRXBUF will take no clock cycles with DMA).

    The last question is how to implement this.  Specifically, would I need to enable a DMA interrupt as well as keep the interrupt for the SPI Receive interrupt operation?  If I need to alter the interrupts, how would I set it up in the main class of my program? Also, I am storing my SPI data into "unsigned char" variables.  Thus, would the DMA source and destination byte be a word or a byte?  Lastly, if I would like to just read the SPI data from the Receive buffer to a variable, do I need to increment the destination address?

    I know there are quite a few questions in there, but I am definitely thankful for the help.  This information is definitely appreciated.

  • dauletle said:
    So from what I understand, if I implement DMA into my code, I can remove the number of clock cycles it takes to read each bit from the SPI Receive Buffer (UCxRXBUF), and thus, only need a single clock cycle to read the UCRXIFG flag indicating that there is data in UCxRXBUF (since reading UCxRXBUF will take no clock cycles with DMA).

    Almost.

    Generally, make some math. The USCI receives one bit at each clock cycle. Let's assume that the master does send with the same baudrate as the slaves MCLK. THen you'll receive one byte every 8 MCLK cycles. Entering and exiting an ISR takes 11. Plus any code inside the ISR. So you'll miss every 2nd or 3rd byte because the CPU isn't fast enough.

    If you program DMA to move any incoming data to memory, the DMA controller will wait for the RXIFG signal. Once it comes, it will syncronize with MCLK (which takes up to 2 MCLK cycles), tehn reads from source (RXBUF) and write to destination. up to 4 MCLK cycles total.
    So the processor still has 50% power left to do something totally unrelated (assuming SPI speed = MCLK speed)

    Note that you won't see the RXIFG flag set, as it is already cleared by the DMA access before the CPU could even read it. And you won't get an RX interrupt.

    So you either have to wait for the DMA interrupt (after the programmed number of transfers) or you check the DMA transfer counter by polling, to see how many bytes have arrived since last check.

    You must not set the RXIE bit (which would the RXIFG bit trigger an ISR and NOT the DMA) and you don't need to enable the DMA interrupt if you don't need an interrupt after n transfers (e.g. you can set up the DMA to fill a ring buffer, beginning at the beginning after the last byte has been written to the end). You can then check the DMA transfer counter to see how far the buffer has been filled right now. No interrupt needed.
    Of course if you know that a command is always, say, 10 bytes, then you can set up the DMA to receive 10 bytes and trigger an interrupt when done. Then the DMA ISR will be called once a complete command has been received.

    dauletle said:
    hus, would the DMA source and destination byte be a word or a byte?

    Programmable. The DMA cannot combine two byte reads to a word write or split a word read into two byte writes. Since RXBUF is a byte, you'll have to set it up for byte transfers.

    dauletle said:
    Lastly, if I would like to just read the SPI data from the Receive buffer to a variable, do I need to increment the destination address?

    You can program the DMA controller to auto-increment the source and/or the destination address. By one per transfer for byte transfers or by 2 per transfer for word transfers.

  • I did begin another post on a similar topic, and I've realized that I was already discussing this before, (except I was referring to doing something differently than just moving the RX data to another location in the memory.

    The issue I am having is that the MSP430 is not returning data to transfer quickly enough.  Specifically, after the SPI master sends the second byte of data to the MSP430, I am trying to access the FRAM using the received SPI data, then send the data from the FRAM to the SPI transmit buffer.  Again, please refer to the link above for details.

    Is it a possibility for the DMA to help me do what I want to do?  I have made a few attempts, but I still have latency issues. Thanks

**Attention** This is a public forum