k64f fast SPI using SDfat SPI FIFO logic from teensy 3.1 SDfat lib. with SPI clock at 30mhz, standard SPI yields 3.7 mbs, fast SPI 27.3mbs https://github.com/manitou48/DUEZoo/blob/master/SPIperf.txt

Dependencies:   mbed

k64f fast SPI using SDfat SPI FIFO logic from teensy 3.1 SDfat lib. with SPI clock at 30mhz, standard SPI yields 3.7 mbs, fast SPI 27.3mbs

https://github.com/manitou48/DUEZoo/blob/master/SPIperf.txt

main.cpp

Committer:
manitou
Date:
2015-11-05
Revision:
0:f9aaa2c9c4a4

File content as of revision 0:f9aaa2c9c4a4:

// k64f fast SPI from teensy 3.1 SDfat lib SPI
#include "mbed.h"

#define PRREG(z) printf(#z" 0x%x\n",z)
Timer tmr;
DigitalOut CSpin(D10);
SPI spi(D11,D12,D13); // mosi, miso, sclk

#define SPI_BUFF_SIZE 1024
uint8_t rx_buffer[SPI_BUFF_SIZE];
uint8_t tx_buffer[SPI_BUFF_SIZE];

void spiperf(int mhz) {
    int i, us;

    spi.frequency(mhz*1000000);
    CSpin=0;
    us = tmr.read_us();
    for(i=0;i<SPI_BUFF_SIZE;i++) spi.write(tx_buffer[i]);
    us = tmr.read_us()-us;
    CSpin=1;
    printf("spi %d mhz %d us %.2f mbs  %0x\n",mhz,us,8.*SPI_BUFF_SIZE/us,SPI0_CTAR0);
}  


#define SPI_INITIAL_FIFO_DEPTH 3

static void spiInit() {
  uint32_t ctar, ctar0, ctar1;
  
  ctar = 0xb8000000;  // 30 mhz
  ctar = 0x38000100;  //15
  ctar = 0xb8020202;  // 4
  ctar = 0x38000101;  // 8
  ctar = 0x38020302;  // 2
  
  // CTAR0 - 8 bit transfer
  ctar0 = ctar | BF_SPI_CTARn_FMSZ(7);
  // CTAR1 - 16 bit transfer
  ctar1 = ctar | BF_SPI_CTARn_FMSZ(15);

  if (SPI0_CTAR0 != ctar0 || SPI0_CTAR1 != ctar1 ) {
    SPI0_MCR = BM_SPI_MCR_MSTR | BM_SPI_MCR_MDIS | BM_SPI_MCR_HALT;
    SPI0_CTAR0 = ctar0;
    SPI0_CTAR1 = ctar1;
  }
  SPI0_MCR = BM_SPI_MCR_MSTR;
}

/** SPI send a byte */
static void spiSend(uint8_t b) {
  SPI0_MCR |= BM_SPI_MCR_CLR_RXF;
  SPI0_SR = BM_SPI_SR_TCF;
  SPI0_PUSHR = b;
  while (!(SPI0_SR & BM_SPI_SR_TCF)) {}
}

/** SPI send multiple bytes */
static void spiSend(const uint8_t* output, size_t len) {
  // clear any data in RX FIFO
  SPI0_MCR = BM_SPI_MCR_MSTR | BM_SPI_MCR_CLR_RXF;
  // use 16 bit frame to avoid TD delay between frames
  // send one byte if len is odd
  if (len & 1) {
    spiSend(*output++);
    len--;
  }
  // initial number of words to push into TX FIFO
  int nf = len/2 < SPI_INITIAL_FIFO_DEPTH ? len/2 : SPI_INITIAL_FIFO_DEPTH;
  // limit for pushing data into TX fifo
  const uint8_t* limit = output + len;
  for (int i = 0; i < nf; i++) {
    uint16_t w = (*output++) << 8;
    w |= *output++;
    SPI0_PUSHR = BM_SPI_PUSHR_CONT | BF_SPI_PUSHR_CTAS(1) | w;
  }
  // write data to TX FIFO
  while (output < limit) {
    uint16_t w = *output++ << 8;
    w |= *output++;
    while (!(SPI0_SR & BM_SPI_SR_RXCTR)) {}
    SPI0_PUSHR = BM_SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w;
    SPI0_POPR;
  }
  // wait for data to be sent
  while (nf) {
    while (!(SPI0_SR & BM_SPI_SR_RXCTR)) {}
    SPI0_POPR;
    nf--;
  }
}
  
int main() {
    uint32_t us, i;
    
    printf("SystemCoreClock %d  %s %s\n",SystemCoreClock,__TIME__,__DATE__);
    tmr.start();
    CSpin =1;
    for(i=0;i<SPI_BUFF_SIZE;i++) tx_buffer[i]=i;
    PRREG(SPI0_MCR);
    PRREG(SPI0_SR);
    PRREG(SPI0_CTAR0);
    PRREG(SPI0_CTAR1);
    spiperf(1);
    spiperf(2);
    spiperf(4);
    spiperf(8);
    spiperf(15);
    spiperf(30);
    
    spiInit();
    CSpin = 0;
    us = tmr.read_us();
    spiSend(tx_buffer,SPI_BUFF_SIZE);
    us = tmr.read_us()-us;
    CSpin=1;
    printf("fastspi  %d us %.2f mbs  %0x\n",us,8.*SPI_BUFF_SIZE/us,SPI0_CTAR0);
}