altos/stm: move spi execution to common ao_spi_run
authorKeith Packard <keithp@keithp.com>
Tue, 28 Jun 2016 06:25:01 +0000 (23:25 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 30 Jun 2016 02:17:45 +0000 (19:17 -0700)
This regularizes SPI hardware use and ensures that the device is
turned off after it has been used and that the status register is back
to 'normal' the next time through.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stm/ao_spi_stm.c

index 3b5773b6ed75e70da31d498eaaf0ecf467356a18..2b6834fdd36a0fa4e12e7ec1b5853e72406336b8 100644 (file)
@@ -84,12 +84,48 @@ validate_spi(struct stm_spi *stm_spi, int which, uint16_t len)
 #define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)
 #endif
 
 #define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)
 #endif
 
+static void
+ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
+
+       validate_spi(stm_spi, which, len);
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (1 << STM_SPI_CR2_TXDMAEN) |
+                       (1 << STM_SPI_CR2_RXDMAEN));
+
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+
+       while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+       while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
+
+       validate_spi(stm_spi, which+1, len);
+
+       stm_spi->cr2 = 0;
+
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
 void
 ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
 {
 void
 ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+       uint8_t id = AO_SPI_INDEX(spi_index);
+       struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -105,9 +141,6 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
-       /* Clear RXNE */
-       (void) stm_spi->dr;
-
        /* Set up the receive DMA -- when this is done, we know the SPI unit
         * is idle. Without this, we'd have to poll waiting for the BSY bit to
         * be cleared
        /* Set up the receive DMA -- when this is done, we know the SPI unit
         * is idle. Without this, we'd have to poll waiting for the BSY bit to
         * be cleared
@@ -124,28 +157,17 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
-       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
-                       (0 << STM_SPI_CR2_RXNEIE) |
-                       (0 << STM_SPI_CR2_ERRIE) |
-                       (0 << STM_SPI_CR2_SSOE) |
-                       (1 << STM_SPI_CR2_TXDMAEN) |
-                       (1 << STM_SPI_CR2_RXDMAEN));
-       ao_dma_start(miso_dma_index);
-       ao_dma_start(mosi_dma_index);
-       ao_arch_critical(
-               while (!ao_dma_done[miso_dma_index])
-                       ao_sleep(&ao_dma_done[miso_dma_index]);
-               );
-       ao_dma_done_transfer(mosi_dma_index);
-       ao_dma_done_transfer(miso_dma_index);
+
+       ao_spi_run(id, 1, len);
 }
 
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
 {
 }
 
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+       uint8_t id = AO_SPI_INDEX(spi_index);
+       struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -161,9 +183,6 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
-       /* Clear RXNE */
-       (void) stm_spi->dr;
-
        /* Set up the receive DMA -- when this is done, we know the SPI unit
         * is idle. Without this, we'd have to poll waiting for the BSY bit to
         * be cleared
        /* Set up the receive DMA -- when this is done, we know the SPI unit
         * is idle. Without this, we'd have to poll waiting for the BSY bit to
         * be cleared
@@ -180,27 +199,16 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
-       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
-                       (0 << STM_SPI_CR2_RXNEIE) |
-                       (0 << STM_SPI_CR2_ERRIE) |
-                       (0 << STM_SPI_CR2_SSOE) |
-                       (1 << STM_SPI_CR2_TXDMAEN) |
-                       (1 << STM_SPI_CR2_RXDMAEN));
-       ao_dma_start(miso_dma_index);
-       ao_dma_start(mosi_dma_index);
-       ao_arch_critical(
-               while (!ao_dma_done[miso_dma_index])
-                       ao_sleep(&ao_dma_done[miso_dma_index]);
-               );
-       ao_dma_done_transfer(mosi_dma_index);
-       ao_dma_done_transfer(miso_dma_index);
+
+       ao_spi_run(id, 3, len);
 }
 
 void
 ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
 {
 }
 
 void
 ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
 {
-       uint8_t         *b = block;
-       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       const uint8_t   *b = block;
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
 
        stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
                        (0 << STM_SPI_CR2_RXNEIE) |
 
        stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
                        (0 << STM_SPI_CR2_RXNEIE) |
@@ -208,22 +216,28 @@ ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
                        (0 << STM_SPI_CR2_SSOE) |
                        (0 << STM_SPI_CR2_TXDMAEN) |
                        (0 << STM_SPI_CR2_RXDMAEN));
                        (0 << STM_SPI_CR2_SSOE) |
                        (0 << STM_SPI_CR2_TXDMAEN) |
                        (0 << STM_SPI_CR2_RXDMAEN));
-
-       /* Clear RXNE */
-       (void) stm_spi->dr;
-
+       validate_spi(stm_spi, 7, len);
        while (len--) {
                while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
                stm_spi->dr = *b++;
        }
        while (len--) {
                while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
                stm_spi->dr = *b++;
        }
+       while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+               ;
+       while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+               ;
+       /* Clear the OVR flag */
+       (void) stm_spi->dr;
+       (void) stm_spi->sr;
+       validate_spi(stm_spi, 8, len);
 }
 
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 {
 }
 
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
+       uint8_t         mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+       uint8_t         miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
 
        spi_dev_null = 0xff;
 
 
        spi_dev_null = 0xff;
 
@@ -241,9 +255,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
-       /* Clear RXNE */
-       (void) stm_spi->dr;
-
        /* Set up the receive DMA to capture data */
        ao_dma_set_transfer(miso_dma_index,
                            &stm_spi->dr,
        /* Set up the receive DMA to capture data */
        ao_dma_set_transfer(miso_dma_index,
                            &stm_spi->dr,
@@ -258,31 +269,16 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
 
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
 
-       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
-                       (0 << STM_SPI_CR2_RXNEIE) |
-                       (0 << STM_SPI_CR2_ERRIE) |
-                       (0 << STM_SPI_CR2_SSOE) |
-                       (1 << STM_SPI_CR2_TXDMAEN) |
-                       (1 << STM_SPI_CR2_RXDMAEN));
-       ao_dma_start(miso_dma_index);
-       ao_dma_start(mosi_dma_index);
-
-       /* Wait until the SPI unit is done */
-       ao_arch_critical(
-               while (!ao_dma_done[miso_dma_index])
-                       ao_sleep(&ao_dma_done[miso_dma_index]);
-               );
-
-       ao_dma_done_transfer(mosi_dma_index);
-       ao_dma_done_transfer(miso_dma_index);
+       ao_spi_run(id, 9, len);
 }
 
 void
 ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
 {
 }
 
 void
 ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
+       uint8_t         mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+       uint8_t         miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
 
        /* Set up transmit DMA to send data */
        ao_dma_set_transfer(mosi_dma_index,
 
        /* Set up transmit DMA to send data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -298,9 +294,6 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
 
-       /* Clear RXNE */
-       (void) stm_spi->dr;
-
        /* Set up the receive DMA to capture data */
        ao_dma_set_transfer(miso_dma_index,
                            &stm_spi->dr,
        /* Set up the receive DMA to capture data */
        ao_dma_set_transfer(miso_dma_index,
                            &stm_spi->dr,
@@ -314,24 +307,7 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
-
-       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
-                       (0 << STM_SPI_CR2_RXNEIE) |
-                       (0 << STM_SPI_CR2_ERRIE) |
-                       (0 << STM_SPI_CR2_SSOE) |
-                       (1 << STM_SPI_CR2_TXDMAEN) |
-                       (1 << STM_SPI_CR2_RXDMAEN));
-       ao_dma_start(miso_dma_index);
-       ao_dma_start(mosi_dma_index);
-
-       /* Wait until the SPI unit is done */
-       ao_arch_critical(
-               while (!ao_dma_done[miso_dma_index])
-                       ao_sleep(&ao_dma_done[miso_dma_index]);
-               );
-
-       ao_dma_done_transfer(mosi_dma_index);
-       ao_dma_done_transfer(miso_dma_index);
+       ao_spi_run(id, 11, len);
 }
 
 static void
 }
 
 static void
@@ -426,20 +402,7 @@ ao_spi_config(uint8_t spi_index, uint32_t speed)
 {
        uint8_t         id = AO_SPI_INDEX(spi_index);
        struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
 {
        uint8_t         id = AO_SPI_INDEX(spi_index);
        struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
-       stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |                   /* Three wire mode */
-                       (0 << STM_SPI_CR1_BIDIOE) |
-                       (0 << STM_SPI_CR1_CRCEN) |                      /* CRC disabled */
-                       (0 << STM_SPI_CR1_CRCNEXT) |
-                       (0 << STM_SPI_CR1_DFF) |
-                       (0 << STM_SPI_CR1_RXONLY) |
-                       (1 << STM_SPI_CR1_SSM) |                        /* Software SS handling */
-                       (1 << STM_SPI_CR1_SSI) |                        /*  ... */
-                       (0 << STM_SPI_CR1_LSBFIRST) |                   /* Big endian */
-                       (1 << STM_SPI_CR1_SPE) |                        /* Enable SPI unit */
-                       (speed << STM_SPI_CR1_BR) |     /* baud rate to pclk/4 */
-                       (1 << STM_SPI_CR1_MSTR) |
-                       (0 << STM_SPI_CR1_CPOL) |                       /* Format 0 */
-                       (0 << STM_SPI_CR1_CPHA));
+
        if (spi_index != ao_spi_index[id]) {
 
                /* Disable old config
        if (spi_index != ao_spi_index[id]) {
 
                /* Disable old config
@@ -454,6 +417,21 @@ ao_spi_config(uint8_t spi_index, uint32_t speed)
                 */
                ao_spi_index[id] = spi_index;
        }
                 */
                ao_spi_index[id] = spi_index;
        }
+       stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |           /* Three wire mode */
+                       (0 << STM_SPI_CR1_BIDIOE) |
+                       (0 << STM_SPI_CR1_CRCEN) |              /* CRC disabled */
+                       (0 << STM_SPI_CR1_CRCNEXT) |
+                       (0 << STM_SPI_CR1_DFF) |
+                       (0 << STM_SPI_CR1_RXONLY) |
+                       (1 << STM_SPI_CR1_SSM) |                /* Software SS handling */
+                       (1 << STM_SPI_CR1_SSI) |                /*  ... */
+                       (0 << STM_SPI_CR1_LSBFIRST) |           /* Big endian */
+                       (1 << STM_SPI_CR1_SPE) |                /* Enable SPI unit */
+                       (speed << STM_SPI_CR1_BR) |             /* baud rate to pclk/4 */
+                       (1 << STM_SPI_CR1_MSTR) |
+                       (0 << STM_SPI_CR1_CPOL) |               /* Format 0 */
+                       (0 << STM_SPI_CR1_CPHA));
+       validate_spi(stm_spi, 13, 0);
 }
 
 uint8_t
 }
 
 uint8_t
@@ -471,6 +449,7 @@ void
 ao_spi_get(uint8_t spi_index, uint32_t speed)
 {
        uint8_t         id = AO_SPI_INDEX(spi_index);
 ao_spi_get(uint8_t spi_index, uint32_t speed)
 {
        uint8_t         id = AO_SPI_INDEX(spi_index);
+
        ao_mutex_get(&ao_spi_mutex[id]);
        ao_spi_config(spi_index, speed);
 }
        ao_mutex_get(&ao_spi_mutex[id]);
        ao_spi_config(spi_index, speed);
 }
@@ -494,13 +473,16 @@ ao_spi_channel_init(uint8_t spi_index)
        ao_spi_disable_index(spi_index);
 
        stm_spi->cr1 = 0;
        ao_spi_disable_index(spi_index);
 
        stm_spi->cr1 = 0;
-       (void) stm_spi->sr;
        stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
                        (0 << STM_SPI_CR2_RXNEIE) |
                        (0 << STM_SPI_CR2_ERRIE) |
                        (0 << STM_SPI_CR2_SSOE) |
                        (0 << STM_SPI_CR2_TXDMAEN) |
                        (0 << STM_SPI_CR2_RXDMAEN));
        stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
                        (0 << STM_SPI_CR2_RXNEIE) |
                        (0 << STM_SPI_CR2_ERRIE) |
                        (0 << STM_SPI_CR2_SSOE) |
                        (0 << STM_SPI_CR2_TXDMAEN) |
                        (0 << STM_SPI_CR2_RXDMAEN));
+
+       /* Clear any pending data and error flags */
+       (void) stm_spi->dr;
+       (void) stm_spi->sr;
 }
 
 #if DEBUG
 }
 
 #if DEBUG