Bläddra i källkod

Merge pull request #23 from KurtE/Faster_transfer_buf

SPI Transfer(buf, cnt) use FIFO 16 bit
main
Paul Stoffregen 7 år sedan
förälder
incheckning
a8af486c7b
2 ändrade filer med 188 tillägg och 31 borttagningar
  1. +184
    -0
      SPI.cpp
  2. +4
    -31
      SPI.h

+ 184
- 0
SPI.cpp Visa fil

@@ -328,6 +328,72 @@ 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) {
if (count > 1)
KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
else
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++;
if (count == 2)
KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CTAS(1);
else
KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CONT | 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 */
@@ -467,6 +533,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;

@@ -598,6 +723,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 Visa fil

@@ -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) {
@@ -691,14 +677,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) {
@@ -881,13 +860,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

Laddar…
Avbryt
Spara