summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2020-04-13 17:09:50 +1000
committerGitHub <noreply@github.com>2020-04-13 17:09:50 +1000
commit46e449376163779413b74f81e320a7d7bbd7e13b (patch)
tree8bd54b95a66d0f2db3a01ce137b3e6bba5ba6f8d /drivers
parent157d121c71104abb564643f7b6152d149c01fc20 (diff)
Fix AVR SPI parameter configuration, remove timeouts due to sync protocol. (#8775)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/avr/spi_master.c123
-rw-r--r--drivers/avr/spi_master.h10
2 files changed, 73 insertions, 60 deletions
diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c
index 3f405ddf5c..32cc55c836 100644
--- a/drivers/avr/spi_master.c
+++ b/drivers/avr/spi_master.c
@@ -34,6 +34,10 @@
 #    define SPI_MISO_PIN B4
 #endif
 
+#ifndef SPI_TIMEOUT
+#    define SPI_TIMEOUT 100
+#endif
+
 static pin_t   currentSlavePin    = NO_PIN;
 static uint8_t currentSlaveConfig = 0;
 static bool    currentSlave2X     = false;
@@ -47,65 +51,74 @@ void spi_init(void) {
     SPCR = (_BV(SPE) | _BV(MSTR));
 }
 
-void spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint8_t divisor) {
-    if (currentSlavePin == NO_PIN && slavePin != NO_PIN) {
-        if (lsbFirst) {
-            currentSlaveConfig |= _BV(DORD);
-        }
+bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
+    if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
+        return false;
+    }
 
-        switch (mode) {
-            case 1:
-                currentSlaveConfig |= _BV(CPHA);
-                break;
-            case 2:
-                currentSlaveConfig |= _BV(CPOL);
-                break;
-            case 3:
-                currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA));
-                break;
-        }
+    currentSlaveConfig = 0;
 
-        uint8_t roundedDivisor = 1;
-        while (roundedDivisor < divisor) {
-            roundedDivisor <<= 1;
-        }
+    if (lsbFirst) {
+        currentSlaveConfig |= _BV(DORD);
+    }
 
-        switch (roundedDivisor) {
-            case 16:
-                currentSlaveConfig |= _BV(SPR0);
-                break;
-            case 64:
-                currentSlaveConfig |= _BV(SPR1);
-                break;
-            case 128:
-                currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0));
-                break;
-            case 2:
-                currentSlave2X = true;
-                break;
-            case 8:
-                currentSlave2X = true;
-                currentSlaveConfig |= _BV(SPR0);
-                break;
-            case 32:
-                currentSlave2X = true;
-                currentSlaveConfig |= _BV(SPR1);
-                break;
-        }
+    switch (mode) {
+        case 1:
+            currentSlaveConfig |= _BV(CPHA);
+            break;
+        case 2:
+            currentSlaveConfig |= _BV(CPOL);
+            break;
+        case 3:
+            currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA));
+            break;
+    }
 
-        SPSR |= currentSlaveConfig;
-        currentSlavePin = slavePin;
-        setPinOutput(currentSlavePin);
-        writePinLow(currentSlavePin);
+    uint16_t roundedDivisor = 1;
+    while (roundedDivisor < divisor) {
+        roundedDivisor <<= 1;
+    }
+
+    switch (roundedDivisor) {
+        case 16:
+            currentSlaveConfig |= _BV(SPR0);
+            break;
+        case 64:
+            currentSlaveConfig |= _BV(SPR1);
+            break;
+        case 128:
+            currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0));
+            break;
+        case 2:
+            currentSlave2X = true;
+            break;
+        case 8:
+            currentSlave2X = true;
+            currentSlaveConfig |= _BV(SPR0);
+            break;
+        case 32:
+            currentSlave2X = true;
+            currentSlaveConfig |= _BV(SPR1);
+            break;
     }
+
+    SPCR |= currentSlaveConfig;
+    if (currentSlave2X) {
+        SPSR |= _BV(SPI2X);
+    }
+    currentSlavePin = slavePin;
+    setPinOutput(currentSlavePin);
+    writePinLow(currentSlavePin);
+
+    return true;
 }
 
-spi_status_t spi_write(uint8_t data, uint16_t timeout) {
+spi_status_t spi_write(uint8_t data) {
     SPDR = data;
 
     uint16_t timeout_timer = timer_read();
     while (!(SPSR & _BV(SPIF))) {
-        if ((timeout != SPI_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+        if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) {
             return SPI_STATUS_TIMEOUT;
         }
     }
@@ -113,12 +126,12 @@ spi_status_t spi_write(uint8_t data, uint16_t timeout) {
     return SPDR;
 }
 
-spi_status_t spi_read(uint16_t timeout) {
+spi_status_t spi_read() {
     SPDR = 0x00;  // Dummy
 
     uint16_t timeout_timer = timer_read();
     while (!(SPSR & _BV(SPIF))) {
-        if ((timeout != SPI_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+        if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) {
             return SPI_STATUS_TIMEOUT;
         }
     }
@@ -126,21 +139,21 @@ spi_status_t spi_read(uint16_t timeout) {
     return SPDR;
 }
 
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length, uint16_t timeout) {
+spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
     spi_status_t status = SPI_STATUS_ERROR;
 
     for (uint16_t i = 0; i < length; i++) {
-        status = spi_write(data[i], timeout);
+        status = spi_write(data[i]);
     }
 
     return status;
 }
 
-spi_status_t spi_receive(uint8_t *data, uint16_t length, uint16_t timeout) {
+spi_status_t spi_receive(uint8_t *data, uint16_t length) {
     spi_status_t status = SPI_STATUS_ERROR;
 
     for (uint16_t i = 0; i < length; i++) {
-        status = spi_read(timeout);
+        status = spi_read();
 
         if (status > 0) {
             data[i] = status;
@@ -155,9 +168,9 @@ void spi_stop(void) {
         setPinOutput(currentSlavePin);
         writePinHigh(currentSlavePin);
         currentSlavePin = NO_PIN;
+        SPSR &= ~(_BV(SPI2X));
         SPCR &= ~(currentSlaveConfig);
         currentSlaveConfig = 0;
-        SPSR               = 0;
         currentSlave2X     = false;
     }
 }
diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h
index 0bab2dc24e..b69c1cbd66 100644
--- a/drivers/avr/spi_master.h
+++ b/drivers/avr/spi_master.h
@@ -41,15 +41,15 @@ extern "C" {
 #endif
 void spi_init(void);
 
-void spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint8_t divisor);
+bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
 
-spi_status_t spi_write(uint8_t data, uint16_t timeout);
+spi_status_t spi_write(uint8_t data);
 
-spi_status_t spi_read(uint16_t timeout);
+spi_status_t spi_read(void);
 
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length, uint16_t timeout);
+spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
 
-spi_status_t spi_receive(uint8_t *data, uint16_t length, uint16_t timeout);
+spi_status_t spi_receive(uint8_t *data, uint16_t length);
 
 void spi_stop(void);
 #ifdef __cplusplus