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.

AM335x McSPI

Hi,

I try to do the following easy task:
Send four bytes out of McSPI0 channel 0 as fast as possile. SPIEN should stay low while transfering the four bytes.
I want to use the FIFO buffers for transmit as well as for receive.

I have read the TRM a lot of times und I have tried a lot of different things but still it does not work.

What I did so far is the following:
- Setup McSPI0 Module with all the clocks and all the other settings
- Set Single mode of operation

Then I do the following:
1. Load the FIFO with the four bytes
2. Set WCNT to 4
3. Force SPIEN to "0" (that works)
4. Enable channel 0
5. Wait until TXFFE is set
6. Disable channel0
7. Force SPIEN to "1" (works fine)
8. Read four bytes from the receive FIFO

And that is the code:

{
  volatile Uint32 dummy;

  HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x91;
  HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x92;
  HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x93;
  HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x94;

  HWREG(SOC_SPI_0_REGS+MCSPI_XFERLEVEL)=(4<<MCSPI_XFERLEVEL_WCNT_SHIFT);

  // Chip Select aktivieren
  HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0))= (HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0)) | MCSPI_CH0CONF_FORCE);

  // Kanal 0 freigeben
  HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0))=(HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0)) | MCSPI_CH0CTRL_EN_ACTIVE);

  // Warten, bis Transmit FIFO leer ist
  while((HWREG(SOC_SPI_0_REGS+MCSPI_CHSTAT(0)) & MCSPI_CH0STAT_TXFFE)==0);

  // Kanal 0 sperren
  HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0))=(HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0)) & ~MCSPI_CH0CTRL_EN_ACTIVE);

  // Chip Select deaktivieren
  HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0))= (HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0)) & ~MCSPI_CH0CONF_FORCE);

  dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
  dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
  dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
  dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
}

Result: SPIEN gets low for about a 1us and then high again. But no SPICLK and no data output. The SPI works without the FIFO so there is nothing wrong with the outputs.

Can a TI AM335x McSPI0 expert show me how to do it?

Thanks and best regards,
Patrick

  • Hi Patrick,
     
    We don't support Starterware code on this forum, only Linux. However it seems to me that you have to write to the FIFO after you enable the channel, not before.
  • Hi Biser,

    What do you mean with "We don't support Starterware code in this forum, only Linux". Did I miss something? Isn't that the AM335x processor forum? Who from TI will give us support on questions like this?

  • Starterware has a dedicated forum: http://e2e.ti.com/support/embedded/starterware/default.aspx. This forum only supports processor hardware and the TI Linux distribution EZSDK.
  • Oh, I see. Thought this is quite close to hardware as a lot of other questions in this forum are (as well as my last post about the glitch on SPI0_CS0 pin). I'm a bit surprised!

  • Anyway, I suggested in my first reply to your post that the issue may be caused by writing to the FIFO before the channel is enabled. Did you try moving the FIFO write after enabling the channel?
  • Although this is not the StarterWare Forum I will show a possible solution that works for me (after days of testing). Maybe some other reader will find it helpful.

    Transmit:
    One trick is to have the chip select forced before activating the channel. Otherwise it does not work. Second trick, as Biser already mentioned, is to fill-up the transmit FIFO after activating the channel.
    Activating TURBO mode reduces the gaps between bytes from around 200ns to less than 100ns. Maybe this is also dependend of the used SPICLK.

    Receive:
    The third trick is to test RXFFE bit and RXS bit to be shure that all the bytes got read. It looks as if the last byte from the FIFO falls into the receive register (SPI_RX) after reading the second last byte and then the RXFFE bits gets set. So one has to test RXS bit to see if there is one more byte to read.
    Reading the receive FIFO is possible after deactivate the chip select and after deactivate the channel.

    So the code now looks like this:

    {
      volatile Uint32 dummy;
    
      // Chip Select aktivieren
      HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0))=(HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0)) | MCSPI_CH0CONF_FORCE);
    
      // Kanal 0 freigeben
      HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0))=(HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0)) | MCSPI_CH0CTRL_EN_ACTIVE);
    
      // Zu sendende Bytes in der FIFO ablegen
      HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x91;
      HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x92;
      HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x93;
      HWREG(SOC_SPI_0_REGS+MCSPI_TX(0))=0x94;
    
      // Warten, bis Transmit FIFO leer ist
      while((HWREG(SOC_SPI_0_REGS+MCSPI_CHSTAT(0)) & MCSPI_CH0STAT_TXFFE)==0)
      {
        // Falls ein Byte in der Empfangs Queue vorhanden ist, dieses auslesen
        if ((HWREG(SOC_SPI_0_REGS+MCSPI_CHSTAT(0)) & MCSPI_CH0STAT_RXFFE)==0)
        {
          dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
        }
      }
      // Kanal 0 sperren
      HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0))=(HWREG(SOC_SPI_0_REGS+MCSPI_CHCTRL(0)) & ~MCSPI_CH0CTRL_EN_ACTIVE);
    
      // Chip Select deaktivieren
      HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0))= (HWREG(SOC_SPI_0_REGS+MCSPI_CHCONF(0)) & ~MCSPI_CH0CONF_FORCE);
    
      // Solange noch Daten in der Empfangs Queue vorhanden sind, diese auslesen
      while(((HWREG(SOC_SPI_0_REGS+MCSPI_CHSTAT(0)) & MCSPI_CH0STAT_RXFFE)==0) ||
            ((HWREG(SOC_SPI_0_REGS+MCSPI_CHSTAT(0)) & MCSPI_CH0STAT_RXS)!=0))
      {
        dummy=HWREG(SOC_SPI_0_REGS+MCSPI_RX(0));
      }
    }

    I really expect TI to come up with this. Maybe is is necessary that TI rewrites the McSPI description in the TRM so that all the mechanism get a bit clearer.

  • Thanks for sharing this Patrick. I will forward your suggestions to the TRM team.