SPI driver for KINETIS K20.

ChibiOS public support forum for topics related to the Freescale Kinetis family of micro-controllers.

Moderator: utzig

User avatar
Giovanni
Site Admin
Posts: 11220
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 398 times
Been thanked: 332 times
Contact:

Re: SPI driver for KINETIS K20.

Postby Giovanni » Mon Sep 22, 2014 8:07 am

Just a note, returning from spiStart() after failing to allocate DMAs is not the usualy behavior, the function is assumed to never fail, you should use assertions there.

Giovanni

fpga_comp
Posts: 16
Joined: Thu Aug 28, 2014 2:00 pm

Re: SPI driver for KINETIS K20.

Postby fpga_comp » Mon Sep 22, 2014 1:52 pm

Thanks. So it would be something that looks like this.

Code: Select all

// can't allocate DMA channels!?
   chDbgAssert((SPID1.DMA_Rx==DMA_NONE_AVAIL)||
               (SPID1.DMA_Tx==DMA_NONE_AVAIL),"No DMA Ch.");

User avatar
Giovanni
Site Admin
Posts: 11220
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 398 times
Been thanked: 332 times
Contact:

Re: SPI driver for KINETIS K20.

Postby Giovanni » Mon Sep 22, 2014 3:22 pm

Exactly, just like the STM32 equivalent does.

I have been thinking about giving xxxStart() functions a failure mode but probably that would only mean moving the problem to the application level.

Giovanni

fpga_comp
Posts: 16
Joined: Thu Aug 28, 2014 2:00 pm

Re: SPI driver for KINETIS K20.

Postby fpga_comp » Tue Sep 23, 2014 4:35 pm

I got the old STM32F103 fatfs demo code compiled and I am testing on my FPGA eval board. ​mmcConnect() failed as the MicroSD card didn't power up.

Here is what I see in ​mmcConnect(). It uses spi_lld_ignore() to send 128 clock pulses.
Image

Code: Select all

/* Use dmaDummy as the source/destination when a buffer is not provided */
 dmaDummy = 0;

While spi_lld_ignore() technically can send whatever it wants, mmcConnect() relies on that particular 0xff value.

Also note that sout value changed after the 5th value. This is because both the Tx/Rx DMA shares a common dummy variable in spi_lld_ignore(). The Tx value get overwritten by the Rx DMA after the Rx FIFO was filled. I think we should split them up as the Rx is toggling. It only cost an extra byte in RAM.

I changed my code to the following:

Code: Select all

volatile uint8_t dmaTxDummy, dmaRxDummy;
                      :
dmaTxDummy = dmaRxDummy = 0xff;
                      :
      DMA->TCD[spip->DMA_Rx].DADDR = (uint32_t)&dmaRxDummy;
                      :
      DMA->TCD[spip->DMA_Tx].SADDR =  (uint32_t)&dmaTxDummy;

Note: the dmaTxDummy, dmaRxDummy do not and cannot be in the stack as DMA would try to access them after the routine returns.

That change get the SD card to toggle it output (Sin pin on the K22) and make mmcConnect() happy. Fat FS get mounted after that.

Image

We are making good progress here!

SpaceCoaster
Posts: 49
Joined: Mon Aug 11, 2014 6:40 am

Re: SPI driver for KINETIS K20.

Postby SpaceCoaster » Tue Sep 23, 2014 4:47 pm

All good, I will include them in my next SPI update.

fpga_comp
Posts: 16
Joined: Thu Aug 28, 2014 2:00 pm

Re: SPI driver for KINETIS K20.

Postby fpga_comp » Tue Sep 23, 2014 11:09 pm

The MMC/SPI driver communicates with the card at the discovery stage for its capability at a slower rate (< 400kbps) and then it get switched to a faster speed (25Mbps) for the actual data transfer.

I notice that the SPI tar0 init code is inside the "if (spip->state == SPI_STOP)" branch. I moved that code after the if statement because the mmc/spi changes its speeds on the fly without stopping/restarting the SPI driver. So a subsequent call to spi_lld_start(), tar0 is not initialized for the higher speed because (state==SPI_STOP) is false.

Edit: the code that sets the SPI byte/word size from the tar0 in the config needs to be moved too.

Code: Select all

void spi_lld_start(SPIDriver *spip) {

  /* If in stopped state then enables the SPI and DMA clocks.*/
  if (spip->state == SPI_STOP) {
                     :
      if (spip->config->tar0) {
        spip->spi->CTAR[0] = spip->config->tar0;
      } else {
        spip->spi->CTAR[0] = KINETIS_SPI_TAR0_DEFAULT;
      }
                      :
   }
    //  <--- move the tar0 block here
 }


By boosting the priority of the thread that calls the SPI (in the demo code), it gets right back into transferring more data instead of every 20ms (as in my previous trace) ! Before these changes, the demo was like floppy drive speed. It took a couple of seconds (1.88s) to mount the sd. Now I can barely see the LED blink! 1.44ms to mount the SD. The SPI is now kept busy as you can see a block of red in the Sck activities vs the tick marks previously! Very nice!
Image


Return to “Kinetis Support”

Who is online

Users browsing this forum: No registered users and 1 guest