diff options
author | Daniel Garcia <danielgarcia@gmail.com> | 2017-03-13 21:47:05 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-13 21:47:05 +0300 |
commit | fbe8c5bb38139370592b52b303e00851208bb2fe (patch) | |
tree | 9ed167bb4aa960c254d6f6af914cc950d8056c9f | |
parent | 77416b5dd0f0f5d419217af7b229033b56853ec2 (diff) | |
parent | 82cb7a9657cdbfb40b08cc3d5eccc0fb67d5c8d4 (diff) |
Merge pull request #420 from mikeburg/bugs/419
Race condition fix for ARMHardwareSPIOutput::waitFully on Teensy 3.1/2
-rw-r--r-- | platforms/arm/k20/fastspi_arm_k20.h | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/platforms/arm/k20/fastspi_arm_k20.h b/platforms/arm/k20/fastspi_arm_k20.h index 7c6e2ade..70210a39 100644 --- a/platforms/arm/k20/fastspi_arm_k20.h +++ b/platforms/arm/k20/fastspi_arm_k20.h @@ -277,13 +277,19 @@ public: static void waitFully() __attribute__((always_inline)) { // Wait for the last byte to get shifted into the register - cli(); - while( (SPIX.SR & 0xF000) > 0) { - // reset the TCF flag - SPIX.SR |= SPI_SR_TCF; - } - sei(); - + bool empty = false; + + do { + cli(); + if ((SPIX.SR & 0xF000) > 0) { + // reset the TCF flag + SPIX.SR |= SPI_SR_TCF; + } else { + empty = true; + } + sei(); + } while (!empty); + // wait for the TCF flag to get set while (!(SPIX.SR & SPI_SR_TCF)); SPIX.SR |= (SPI_SR_TCF | SPI_SR_EOQF); @@ -308,36 +314,40 @@ public: public: static void writeWord(uint16_t w) __attribute__((always_inline)) { if(WAIT_STATE == PRE) { wait(); } + cli(); SPIX.PUSHR = ((LAST_STATE == LAST) ? SPI_PUSHR_EOQ : 0) | ((CONT_STATE == CONT) ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF; + sei(); if(WAIT_STATE == POST) { wait(); } } static void writeByte(uint8_t b) __attribute__((always_inline)) { if(WAIT_STATE == PRE) { wait(); } + cli(); SPIX.PUSHR = ((LAST_STATE == LAST) ? SPI_PUSHR_EOQ : 0) | ((CONT_STATE == CONT) ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; + sei(); if(WAIT_STATE == POST) { wait(); } } }; - static void writeWord(uint16_t w) __attribute__((always_inline)) { wait(); SPIX.PUSHR = SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF;} - static void writeWordNoWait(uint16_t w) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF;} + static void writeWord(uint16_t w) __attribute__((always_inline)) { wait(); cli(); SPIX.PUSHR = SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF; sei(); } + static void writeWordNoWait(uint16_t w) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF; sei(); } - static void writeByte(uint8_t b) __attribute__((always_inline)) { wait(); SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF;} - static void writeBytePostWait(uint8_t b) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF);SPIX.SR |= SPI_SR_TCF; wait(); } - static void writeByteNoWait(uint8_t b) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF;} + static void writeByte(uint8_t b) __attribute__((always_inline)) { wait(); cli(); SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; sei(); } + static void writeBytePostWait(uint8_t b) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF);SPIX.SR |= SPI_SR_TCF; sei(); wait(); } + static void writeByteNoWait(uint8_t b) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; sei(); } - static void writeWordCont(uint16_t w) __attribute__((always_inline)) { wait(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF;} - static void writeWordContNoWait(uint16_t w) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF;} + static void writeWordCont(uint16_t w) __attribute__((always_inline)) { wait(); cli(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF; sei(); } + static void writeWordContNoWait(uint16_t w) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | (w & 0xFFFF); SPIX.SR |= SPI_SR_TCF; sei();} - static void writeByteCont(uint8_t b) __attribute__((always_inline)) { wait(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF;} - static void writeByteContPostWait(uint8_t b) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF;wait(); } - static void writeByteContNoWait(uint8_t b) __attribute__((always_inline)) { SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF;} + static void writeByteCont(uint8_t b) __attribute__((always_inline)) { wait(); cli(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; sei(); } + static void writeByteContPostWait(uint8_t b) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; sei(); wait(); } + static void writeByteContNoWait(uint8_t b) __attribute__((always_inline)) { cli(); SPIX.PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0) | (b & 0xFF); SPIX.SR |= SPI_SR_TCF; sei(); } // not the most efficient mechanism in the world - but should be enough for sm16716 and friends template <uint8_t BIT> inline static void writeBit(uint8_t b) { |