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
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@0:f9aaa2c9c4a4, 2015-11-05 (annotated)
- Committer:
- manitou
- Date:
- Thu Nov 05 18:40:14 2015 +0000
- Revision:
- 0:f9aaa2c9c4a4
k64f fast SPI proof of concept
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
manitou | 0:f9aaa2c9c4a4 | 1 | // k64f fast SPI from teensy 3.1 SDfat lib SPI |
manitou | 0:f9aaa2c9c4a4 | 2 | #include "mbed.h" |
manitou | 0:f9aaa2c9c4a4 | 3 | |
manitou | 0:f9aaa2c9c4a4 | 4 | #define PRREG(z) printf(#z" 0x%x\n",z) |
manitou | 0:f9aaa2c9c4a4 | 5 | Timer tmr; |
manitou | 0:f9aaa2c9c4a4 | 6 | DigitalOut CSpin(D10); |
manitou | 0:f9aaa2c9c4a4 | 7 | SPI spi(D11,D12,D13); // mosi, miso, sclk |
manitou | 0:f9aaa2c9c4a4 | 8 | |
manitou | 0:f9aaa2c9c4a4 | 9 | #define SPI_BUFF_SIZE 1024 |
manitou | 0:f9aaa2c9c4a4 | 10 | uint8_t rx_buffer[SPI_BUFF_SIZE]; |
manitou | 0:f9aaa2c9c4a4 | 11 | uint8_t tx_buffer[SPI_BUFF_SIZE]; |
manitou | 0:f9aaa2c9c4a4 | 12 | |
manitou | 0:f9aaa2c9c4a4 | 13 | void spiperf(int mhz) { |
manitou | 0:f9aaa2c9c4a4 | 14 | int i, us; |
manitou | 0:f9aaa2c9c4a4 | 15 | |
manitou | 0:f9aaa2c9c4a4 | 16 | spi.frequency(mhz*1000000); |
manitou | 0:f9aaa2c9c4a4 | 17 | CSpin=0; |
manitou | 0:f9aaa2c9c4a4 | 18 | us = tmr.read_us(); |
manitou | 0:f9aaa2c9c4a4 | 19 | for(i=0;i<SPI_BUFF_SIZE;i++) spi.write(tx_buffer[i]); |
manitou | 0:f9aaa2c9c4a4 | 20 | us = tmr.read_us()-us; |
manitou | 0:f9aaa2c9c4a4 | 21 | CSpin=1; |
manitou | 0:f9aaa2c9c4a4 | 22 | printf("spi %d mhz %d us %.2f mbs %0x\n",mhz,us,8.*SPI_BUFF_SIZE/us,SPI0_CTAR0); |
manitou | 0:f9aaa2c9c4a4 | 23 | } |
manitou | 0:f9aaa2c9c4a4 | 24 | |
manitou | 0:f9aaa2c9c4a4 | 25 | |
manitou | 0:f9aaa2c9c4a4 | 26 | #define SPI_INITIAL_FIFO_DEPTH 3 |
manitou | 0:f9aaa2c9c4a4 | 27 | |
manitou | 0:f9aaa2c9c4a4 | 28 | static void spiInit() { |
manitou | 0:f9aaa2c9c4a4 | 29 | uint32_t ctar, ctar0, ctar1; |
manitou | 0:f9aaa2c9c4a4 | 30 | |
manitou | 0:f9aaa2c9c4a4 | 31 | ctar = 0xb8000000; // 30 mhz |
manitou | 0:f9aaa2c9c4a4 | 32 | ctar = 0x38000100; //15 |
manitou | 0:f9aaa2c9c4a4 | 33 | ctar = 0xb8020202; // 4 |
manitou | 0:f9aaa2c9c4a4 | 34 | ctar = 0x38000101; // 8 |
manitou | 0:f9aaa2c9c4a4 | 35 | ctar = 0x38020302; // 2 |
manitou | 0:f9aaa2c9c4a4 | 36 | |
manitou | 0:f9aaa2c9c4a4 | 37 | // CTAR0 - 8 bit transfer |
manitou | 0:f9aaa2c9c4a4 | 38 | ctar0 = ctar | BF_SPI_CTARn_FMSZ(7); |
manitou | 0:f9aaa2c9c4a4 | 39 | // CTAR1 - 16 bit transfer |
manitou | 0:f9aaa2c9c4a4 | 40 | ctar1 = ctar | BF_SPI_CTARn_FMSZ(15); |
manitou | 0:f9aaa2c9c4a4 | 41 | |
manitou | 0:f9aaa2c9c4a4 | 42 | if (SPI0_CTAR0 != ctar0 || SPI0_CTAR1 != ctar1 ) { |
manitou | 0:f9aaa2c9c4a4 | 43 | SPI0_MCR = BM_SPI_MCR_MSTR | BM_SPI_MCR_MDIS | BM_SPI_MCR_HALT; |
manitou | 0:f9aaa2c9c4a4 | 44 | SPI0_CTAR0 = ctar0; |
manitou | 0:f9aaa2c9c4a4 | 45 | SPI0_CTAR1 = ctar1; |
manitou | 0:f9aaa2c9c4a4 | 46 | } |
manitou | 0:f9aaa2c9c4a4 | 47 | SPI0_MCR = BM_SPI_MCR_MSTR; |
manitou | 0:f9aaa2c9c4a4 | 48 | } |
manitou | 0:f9aaa2c9c4a4 | 49 | |
manitou | 0:f9aaa2c9c4a4 | 50 | /** SPI send a byte */ |
manitou | 0:f9aaa2c9c4a4 | 51 | static void spiSend(uint8_t b) { |
manitou | 0:f9aaa2c9c4a4 | 52 | SPI0_MCR |= BM_SPI_MCR_CLR_RXF; |
manitou | 0:f9aaa2c9c4a4 | 53 | SPI0_SR = BM_SPI_SR_TCF; |
manitou | 0:f9aaa2c9c4a4 | 54 | SPI0_PUSHR = b; |
manitou | 0:f9aaa2c9c4a4 | 55 | while (!(SPI0_SR & BM_SPI_SR_TCF)) {} |
manitou | 0:f9aaa2c9c4a4 | 56 | } |
manitou | 0:f9aaa2c9c4a4 | 57 | |
manitou | 0:f9aaa2c9c4a4 | 58 | /** SPI send multiple bytes */ |
manitou | 0:f9aaa2c9c4a4 | 59 | static void spiSend(const uint8_t* output, size_t len) { |
manitou | 0:f9aaa2c9c4a4 | 60 | // clear any data in RX FIFO |
manitou | 0:f9aaa2c9c4a4 | 61 | SPI0_MCR = BM_SPI_MCR_MSTR | BM_SPI_MCR_CLR_RXF; |
manitou | 0:f9aaa2c9c4a4 | 62 | // use 16 bit frame to avoid TD delay between frames |
manitou | 0:f9aaa2c9c4a4 | 63 | // send one byte if len is odd |
manitou | 0:f9aaa2c9c4a4 | 64 | if (len & 1) { |
manitou | 0:f9aaa2c9c4a4 | 65 | spiSend(*output++); |
manitou | 0:f9aaa2c9c4a4 | 66 | len--; |
manitou | 0:f9aaa2c9c4a4 | 67 | } |
manitou | 0:f9aaa2c9c4a4 | 68 | // initial number of words to push into TX FIFO |
manitou | 0:f9aaa2c9c4a4 | 69 | int nf = len/2 < SPI_INITIAL_FIFO_DEPTH ? len/2 : SPI_INITIAL_FIFO_DEPTH; |
manitou | 0:f9aaa2c9c4a4 | 70 | // limit for pushing data into TX fifo |
manitou | 0:f9aaa2c9c4a4 | 71 | const uint8_t* limit = output + len; |
manitou | 0:f9aaa2c9c4a4 | 72 | for (int i = 0; i < nf; i++) { |
manitou | 0:f9aaa2c9c4a4 | 73 | uint16_t w = (*output++) << 8; |
manitou | 0:f9aaa2c9c4a4 | 74 | w |= *output++; |
manitou | 0:f9aaa2c9c4a4 | 75 | SPI0_PUSHR = BM_SPI_PUSHR_CONT | BF_SPI_PUSHR_CTAS(1) | w; |
manitou | 0:f9aaa2c9c4a4 | 76 | } |
manitou | 0:f9aaa2c9c4a4 | 77 | // write data to TX FIFO |
manitou | 0:f9aaa2c9c4a4 | 78 | while (output < limit) { |
manitou | 0:f9aaa2c9c4a4 | 79 | uint16_t w = *output++ << 8; |
manitou | 0:f9aaa2c9c4a4 | 80 | w |= *output++; |
manitou | 0:f9aaa2c9c4a4 | 81 | while (!(SPI0_SR & BM_SPI_SR_RXCTR)) {} |
manitou | 0:f9aaa2c9c4a4 | 82 | SPI0_PUSHR = BM_SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w; |
manitou | 0:f9aaa2c9c4a4 | 83 | SPI0_POPR; |
manitou | 0:f9aaa2c9c4a4 | 84 | } |
manitou | 0:f9aaa2c9c4a4 | 85 | // wait for data to be sent |
manitou | 0:f9aaa2c9c4a4 | 86 | while (nf) { |
manitou | 0:f9aaa2c9c4a4 | 87 | while (!(SPI0_SR & BM_SPI_SR_RXCTR)) {} |
manitou | 0:f9aaa2c9c4a4 | 88 | SPI0_POPR; |
manitou | 0:f9aaa2c9c4a4 | 89 | nf--; |
manitou | 0:f9aaa2c9c4a4 | 90 | } |
manitou | 0:f9aaa2c9c4a4 | 91 | } |
manitou | 0:f9aaa2c9c4a4 | 92 | |
manitou | 0:f9aaa2c9c4a4 | 93 | int main() { |
manitou | 0:f9aaa2c9c4a4 | 94 | uint32_t us, i; |
manitou | 0:f9aaa2c9c4a4 | 95 | |
manitou | 0:f9aaa2c9c4a4 | 96 | printf("SystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); |
manitou | 0:f9aaa2c9c4a4 | 97 | tmr.start(); |
manitou | 0:f9aaa2c9c4a4 | 98 | CSpin =1; |
manitou | 0:f9aaa2c9c4a4 | 99 | for(i=0;i<SPI_BUFF_SIZE;i++) tx_buffer[i]=i; |
manitou | 0:f9aaa2c9c4a4 | 100 | PRREG(SPI0_MCR); |
manitou | 0:f9aaa2c9c4a4 | 101 | PRREG(SPI0_SR); |
manitou | 0:f9aaa2c9c4a4 | 102 | PRREG(SPI0_CTAR0); |
manitou | 0:f9aaa2c9c4a4 | 103 | PRREG(SPI0_CTAR1); |
manitou | 0:f9aaa2c9c4a4 | 104 | spiperf(1); |
manitou | 0:f9aaa2c9c4a4 | 105 | spiperf(2); |
manitou | 0:f9aaa2c9c4a4 | 106 | spiperf(4); |
manitou | 0:f9aaa2c9c4a4 | 107 | spiperf(8); |
manitou | 0:f9aaa2c9c4a4 | 108 | spiperf(15); |
manitou | 0:f9aaa2c9c4a4 | 109 | spiperf(30); |
manitou | 0:f9aaa2c9c4a4 | 110 | |
manitou | 0:f9aaa2c9c4a4 | 111 | spiInit(); |
manitou | 0:f9aaa2c9c4a4 | 112 | CSpin = 0; |
manitou | 0:f9aaa2c9c4a4 | 113 | us = tmr.read_us(); |
manitou | 0:f9aaa2c9c4a4 | 114 | spiSend(tx_buffer,SPI_BUFF_SIZE); |
manitou | 0:f9aaa2c9c4a4 | 115 | us = tmr.read_us()-us; |
manitou | 0:f9aaa2c9c4a4 | 116 | CSpin=1; |
manitou | 0:f9aaa2c9c4a4 | 117 | printf("fastspi %d us %.2f mbs %0x\n",us,8.*SPI_BUFF_SIZE/us,SPI0_CTAR0); |
manitou | 0:f9aaa2c9c4a4 | 118 | } |