ソースを参照

SPI Transfer(buf, cnt) use FIFO 16 bit

Update SPI.transfer(buf, cnt) to use the FIFO queue to speed things up.
It also speeds things up to pack the data into 16 bit transfers instead
of 8 bits.

As this code is more complicated,  no longer makes sense to inline it,
so functions moved from .h to .cpp files.

SPI1 and SPI2 transfer functions were updated as well for T3.5 and T3.6
main
Kurt Eckhardt 8年前
コミット
0257d0473e
2個のファイルの変更182行の追加31行の削除
  1. +178
    -0
      SPI.cpp
  2. +4
    -31
      SPI.h

+ 178
- 0
SPI.cpp ファイルの表示

@@ -325,6 +325,66 @@ uint8_t SPIClass::setCS(uint8_t pin)
}


void SPIClass::transfer(void *buf, size_t count) {
if (count == 0) return;
uint8_t *p_write = (uint8_t *)buf;
uint8_t *p_read = p_write;
size_t count_read = count;

// Lets clear the reader queue
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);

uint32_t sr;

// Now lets loop while we still have data to output
if (count & 1) {
KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
count--;
}

while (count > 0) {

// Push out the next byte;
uint16_t w = (*p_write++) << 8;
w |= *p_write++;
KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CTAS(1);
count -= 2; // how many bytes to output.
// Make sure queue is not full before pushing next byte out
do {
sr = KINETISK_SPI0.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
} while ((sr & (15 << 12)) > (3 << 12));

}

// now lets wait for all of the read bytes to be returned...
while (count_read) {
sr = KINETISK_SPI0.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
}
}



/**********************************************************/
/* 32 bit Teensy-3.5/3.6 */
@@ -463,6 +523,65 @@ uint8_t SPI1Class::setCS(uint8_t pin)
return 0;
}

void SPI1Class::transfer(void *buf, size_t count) {
if (count == 0) return;
uint8_t *p_write = (uint8_t *)buf;
uint8_t *p_read = p_write;
size_t count_read = count;

// Lets clear the reader queue
SPI1_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);

uint32_t sr;

// Now lets loop while we still have data to output
if (count & 1) {
KINETISK_SPI1.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
count--;
}

while (count > 0) {

// Push out the next byte;
uint16_t w = (*p_write++) << 8;
w |= *p_write++;
KINETISK_SPI1.PUSHR = w | SPI_PUSHR_CTAS(1);
count -= 2; // how many bytes to output.
// Make sure queue is not full before pushing next byte out
do {
sr = KINETISK_SPI1.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
} while ((sr & (15 << 12)) > (0 << 12)); // SPI1 and 2 only have 1 item queue

}

// now lets wait for all of the read bytes to be returned...
while (count_read) {
sr = KINETISK_SPI1.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
}
}

// SPI2 Class
SPI2Class SPI2;

@@ -593,6 +712,65 @@ uint8_t SPI2Class::setCS(uint8_t pin)
return 0;
}

void SPI2Class::transfer(void *buf, size_t count) {
if (count == 0) return;
uint8_t *p_write = (uint8_t *)buf;
uint8_t *p_read = p_write;
size_t count_read = count;

// Lets clear the reader queue
SPI2_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);

uint32_t sr;

// Now lets loop while we still have data to output
if (count & 1) {
KINETISK_SPI2.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
count--;
}

while (count > 0) {

// Push out the next byte;
uint16_t w = (*p_write++) << 8;
w |= *p_write++;
KINETISK_SPI2.PUSHR = w | SPI_PUSHR_CTAS(1);
count -= 2; // how many bytes to output.
// Make sure queue is not full before pushing next byte out
do {
sr = KINETISK_SPI2.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
} while ((sr & (15 << 12)) > (0 << 12)); // SPI2 and 2 only have 1 item queue

}

// now lets wait for all of the read bytes to be returned...
while (count_read) {
sr = KINETISK_SPI2.SR;
if (sr & 0xF0) {
uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in
count_read--;
} else {
*p_read++ = w >> 8;
*p_read++ = (w & 0xff);
count_read -= 2;
}
}
}
}


#endif


+ 4
- 31
SPI.h ファイルの表示

@@ -298,7 +298,7 @@ private:


/**********************************************************/
/* 32 bit Teensy 3.0 and 3.1 */
/* 32 bit Teensy 3.0 and 3.1, 3.2, 3.5, 3.6 */
/**********************************************************/

#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
@@ -488,21 +488,7 @@ public:
while (!(SPI0_SR & SPI_SR_TCF)) ; // wait
return SPI0_POPR;
}
inline static void transfer(void *buf, size_t count) {
if (count == 0) return;
uint8_t *p = (uint8_t *)buf;
SPDR = *p;
while (--count > 0) {
uint8_t out = *(p + 1);
while (!(SPSR & _BV(SPIF))) ;
uint8_t in = SPDR;
SPDR = out;
*p++ = in;
}
while (!(SPSR & _BV(SPIF))) ;
*p = SPDR;
}

static void transfer(void *buf, size_t count);
// After performing a group of transfers and releasing the chip select
// signal, this function allows others to access the SPI bus
inline static void endTransaction(void) {
@@ -689,14 +675,7 @@ public:
while (!(SPI1_SR & SPI_SR_TCF)) ; // wait
return SPI1_POPR;
}
inline static void transfer(void *buf, size_t count) {
uint8_t *p = (uint8_t *)buf;
while (count--) {
*p = transfer(*p);
p++;
}
}

static void transfer(void *buf, size_t count);
// After performing a group of transfers and releasing the chip select
// signal, this function allows others to access the SPI bus
inline static void endTransaction(void) {
@@ -877,13 +856,7 @@ public:
while (!(SPI2_SR & SPI_SR_TCF)) ; // wait
return SPI2_POPR;
}
inline static void transfer(void *buf, size_t count) {
uint8_t *p = (uint8_t *)buf;
while (count--) {
*p = transfer(*p);
p++;
}
}
static void transfer(void *buf, size_t count);

// After performing a group of transfers and releasing the chip select
// signal, this function allows others to access the SPI bus

読み込み中…
キャンセル
保存