Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 8416e2cbf -> 0fa458469


stm32f4 spi; async tx with master was not leaving spi in proper state.
Keep clock line in proper idle state in modes 2 & 3.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/0fa45846
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/0fa45846
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/0fa45846

Branch: refs/heads/develop
Commit: 0fa458469ad7d20fe057b644858dd78869996957
Parents: 8416e2c
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Sun Oct 16 23:02:52 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Sun Oct 16 23:11:21 2016 -0700

----------------------------------------------------------------------
 hw/mcu/stm/stm32f4xx/src/hal_spi.c | 341 +++++++++++++++++++++-----------
 1 file changed, 223 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0fa45846/hw/mcu/stm/stm32f4xx/src/hal_spi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/stm/stm32f4xx/src/hal_spi.c 
b/hw/mcu/stm/stm32f4xx/src/hal_spi.c
index c307398..8535414 100644
--- a/hw/mcu/stm/stm32f4xx/src/hal_spi.c
+++ b/hw/mcu/stm/stm32f4xx/src/hal_spi.c
@@ -35,7 +35,6 @@
 #include "mcu/stm32f4xx_mynewt_hal.h"
 #include "mcu/stm32f4_bsp.h"
 #include "bsp/cmsis_nvic.h"
-#include "console/console.h"
 
 #define STM32F4_HAL_SPI_TIMEOUT (1000)
 
@@ -43,8 +42,11 @@
 
 struct stm32f4_hal_spi {
     SPI_HandleTypeDef handle;
-    uint8_t type;
-    uint16_t def_char;
+    uint8_t slave:1;
+    uint8_t tx_in_prog:1;
+    uint8_t selected:1;
+    uint8_t def_char[4];
+    struct stm32f4_hal_spi_cfg *cfg;
     /* Callback and arguments */
     hal_spi_txrx_cb txrx_cb_func;
     void            *txrx_cb_arg;
@@ -52,6 +54,7 @@ struct stm32f4_hal_spi {
 
 static struct stm32f4_spi_stat {
     uint32_t irq;
+    uint32_t ss_irq;
 } spi_stat;
 
 static void spi_irq_handler(struct stm32f4_hal_spi *spi);
@@ -149,18 +152,83 @@ stm32f4_resolve_spi_irq(SPI_HandleTypeDef *hspi)
 }
 
 static void
-spi_irq_handler(struct stm32f4_hal_spi *spi)
+spim_irq_handler(struct stm32f4_hal_spi *spi)
 {
-    spi_stat.irq++;
     HAL_SPI_IRQHandler(&spi->handle);
-    if (spi->type == HAL_SPI_TYPE_MASTER && spi->handle.TxXferCount == 0 &&
-      spi->handle.RxXferCount) {
+
+    if (spi->handle.TxXferCount == 0 && spi->handle.RxXferCount == 0) {
+        spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
         if (spi->txrx_cb_func) {
             spi->txrx_cb_func(spi->txrx_cb_arg, spi->handle.TxXferSize);
         }
     }
-    if (spi->type == HAL_SPI_TYPE_SLAVE) {
-        spi->handle.Instance->DR = spi->def_char;
+}
+
+static void
+spis_irq_handler(struct stm32f4_hal_spi *spi)
+{
+    HAL_SPI_IRQHandler(&spi->handle);
+    if (spi->tx_in_prog) {
+        if (spi->handle.TxXferCount == 0 && spi->handle.RxXferCount == 0) {
+            spi->tx_in_prog = 0;
+
+            HAL_SPI_Transmit_IT(&spi->handle, spi->def_char, 2);
+
+            if (spi->txrx_cb_func) {
+                spi->txrx_cb_func(spi->txrx_cb_arg, spi->handle.TxXferSize);
+            }
+        }
+    } else {
+        spi->handle.pTxBuffPtr = spi->def_char;
+        spi->handle.TxXferCount = 2;
+    }
+}
+
+static void
+spi_irq_handler(struct stm32f4_hal_spi *spi)
+{
+    spi_stat.irq++;
+    if (!spi->slave) {
+        spim_irq_handler(spi);
+    } else {
+        spis_irq_handler(spi);
+    }
+}
+
+static void
+spi_ss_isr(void *arg)
+{
+    struct stm32f4_hal_spi *spi = (struct stm32f4_hal_spi *)arg;
+    int ss;
+    int len;
+    int rc;
+
+    spi_stat.ss_irq++;
+    ss = hal_gpio_read(spi->cfg->ss_pin);
+    if (ss == 0 && !spi->selected) {
+        spi->handle.Instance->CR1 |= (SPI_CR1_SSI | SPI_CR1_SPE);
+        if (spi->tx_in_prog) {
+            rc = HAL_SPI_TransmitReceive_IT(&spi->handle,
+              spi->handle.pTxBuffPtr, spi->handle.pRxBuffPtr,
+              spi->handle.TxXferSize);
+        } else {
+            rc = HAL_SPI_Transmit_IT(&spi->handle, spi->def_char, 2);
+        }
+        assert(rc == 0);
+        spi->selected = 1;
+    }
+    if (ss == 1 && spi->selected) {
+        spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
+        len = spi->handle.RxXferSize - spi->handle.RxXferCount;
+        if (spi->tx_in_prog && len) {
+            spi->tx_in_prog = 0;
+
+            if (spi->txrx_cb_func) {
+                spi->txrx_cb_func(spi->txrx_cb_arg, len);
+            }
+        }
+        spi->handle.State = HAL_SPI_STATE_READY;
+        spi->selected = 0;
     }
 }
 
@@ -238,9 +306,6 @@ int
 hal_spi_init(int spi_num, void *usercfg, uint8_t spi_type)
 {
     struct stm32f4_hal_spi *spi;
-    struct stm32f4_hal_spi_cfg *cfg;
-    GPIO_InitTypeDef gpio;
-    IRQn_Type irq;
     int rc;
 
     /* Check for valid arguments */
@@ -259,90 +324,8 @@ hal_spi_init(int spi_num, void *usercfg, uint8_t spi_type)
      */
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
 
-    cfg = (struct stm32f4_hal_spi_cfg *) usercfg;
-
-    spi->type = spi_type;
-    if (spi_type == HAL_SPI_TYPE_MASTER) {
-        spi->handle.Init.NSS = SPI_NSS_SOFT;
-        spi->handle.Init.Mode = SPI_MODE_MASTER;
-    } else {
-        spi->handle.Init.NSS = SPI_NSS_HARD_INPUT;
-        spi->handle.Init.Mode = SPI_MODE_SLAVE;
-    }
-
-    gpio.Mode = GPIO_MODE_AF_PP;
-    gpio.Pull = GPIO_NOPULL;
-    gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
-
-    /* Enable the clocks for this SPI */
-    switch (spi_num) {
-        case 0:
-            __HAL_RCC_SPI1_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF5_SPI1;
-            spi->handle.Instance = SPI1;
-            break;
-        case 1:
-            __HAL_RCC_SPI2_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF5_SPI2;
-            spi->handle.Instance = SPI2;
-            break;
-        case 2:
-            __HAL_RCC_SPI3_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF6_SPI3;
-            spi->handle.Instance = SPI3;
-            break;
-#ifdef SPI4
-        case 3:
-            __HAL_RCC_SPI4_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF5_SPI4;
-            spi->handle.Instance = SPI4;
-            break;
-#endif
-#ifdef SPI5
-        case 4:
-            __HAL_RCC_SPI5_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF5_SPI5;
-            spi->handle.Instance = SPI5;
-            break;
-#endif
-#ifdef SPI6
-        case 5:
-            __HAL_RCC_SPI6_CLK_ENABLE();
-            gpio.Alternate = GPIO_AF5_SPI6;
-            spi->handle.Instance = SPI6;
-            break;
-#endif
-       default:
-            assert(0);
-            rc = -1;
-            goto err;
-    }
-
-    rc = hal_gpio_init_stm(cfg->sck_pin, &gpio);
-    if (rc != 0) {
-        goto err;
-    }
-    rc = hal_gpio_init_stm(cfg->mosi_pin, &gpio);
-    if (rc != 0) {
-        goto err;
-    }
-
-    rc = hal_gpio_init_stm(cfg->miso_pin, &gpio);
-    if (rc != 0) {
-        goto err;
-    }
-    if (spi_type == HAL_SPI_TYPE_SLAVE) {
-        gpio.Pull = GPIO_PULLUP;
-        rc = hal_gpio_init_stm(cfg->ss_pin, &gpio);
-        if (rc != 0) {
-            goto err;
-        }
-    }
-
-    irq = stm32f4_resolve_spi_irq(&spi->handle);
-    NVIC_SetPriority(irq, cfg->irq_prio);
-    NVIC_SetVector(irq, stm32f4_resolve_spi_irq_handler(&spi->handle));
-    NVIC_EnableIRQ(irq);
+    spi->cfg = usercfg;
+    spi->slave = (spi_type == HAL_SPI_TYPE_SLAVE);
 
     return (0);
 err:
@@ -462,7 +445,7 @@ hal_spi_disable(int spi_num)
     rc = 0;
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->type == HAL_SPI_TYPE_MASTER) {
+    if (!spi->slave) {
         spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
     }
     /* XXX power down */
@@ -474,7 +457,10 @@ int
 hal_spi_config(int spi_num, struct hal_spi_settings *settings)
 {
     struct stm32f4_hal_spi *spi;
+    struct stm32f4_hal_spi_cfg *cfg;
     SPI_InitTypeDef *init;
+    GPIO_InitTypeDef gpio;
+    IRQn_Type irq;
     uint32_t prescaler;
     int rc;
 
@@ -482,6 +468,96 @@ hal_spi_config(int spi_num, struct hal_spi_settings 
*settings)
 
     init = &spi->handle.Init;
 
+    cfg = spi->cfg;
+
+    if (!spi->slave) {
+        spi->handle.Init.NSS = SPI_NSS_SOFT;
+        spi->handle.Init.Mode = SPI_MODE_MASTER;
+    } else {
+        spi->handle.Init.NSS = SPI_NSS_SOFT;
+        spi->handle.Init.Mode = SPI_MODE_SLAVE;
+    }
+
+    gpio.Mode = GPIO_MODE_AF_PP;
+    gpio.Pull = GPIO_NOPULL;
+    gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+
+    /* Enable the clocks for this SPI */
+    switch (spi_num) {
+        case 0:
+            __HAL_RCC_SPI1_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF5_SPI1;
+            spi->handle.Instance = SPI1;
+            break;
+        case 1:
+            __HAL_RCC_SPI2_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF5_SPI2;
+            spi->handle.Instance = SPI2;
+            break;
+        case 2:
+            __HAL_RCC_SPI3_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF6_SPI3;
+            spi->handle.Instance = SPI3;
+            break;
+#ifdef SPI4
+        case 3:
+            __HAL_RCC_SPI4_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF5_SPI4;
+            spi->handle.Instance = SPI4;
+            break;
+#endif
+#ifdef SPI5
+        case 4:
+            __HAL_RCC_SPI5_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF5_SPI5;
+            spi->handle.Instance = SPI5;
+            break;
+#endif
+#ifdef SPI6
+        case 5:
+            __HAL_RCC_SPI6_CLK_ENABLE();
+            gpio.Alternate = GPIO_AF5_SPI6;
+            spi->handle.Instance = SPI6;
+            break;
+#endif
+       default:
+            assert(0);
+            rc = -1;
+            goto err;
+    }
+
+    if (!spi->slave) {
+        if (settings->data_mode == HAL_SPI_MODE2 ||
+          settings->data_mode == HAL_SPI_MODE3) {
+            gpio.Pull = GPIO_PULLUP;
+        } else {
+            gpio.Pull = GPIO_PULLDOWN;
+        }
+    }
+    rc = hal_gpio_init_stm(cfg->sck_pin, &gpio);
+    if (rc != 0) {
+        goto err;
+    }
+    if (!spi->slave) {
+        gpio.Pull = GPIO_NOPULL;
+    } else {
+        gpio.Mode = GPIO_MODE_AF_OD;
+    }
+
+    rc = hal_gpio_init_stm(cfg->mosi_pin, &gpio);
+    if (rc != 0) {
+        goto err;
+    }
+    if (!spi->slave) {
+        gpio.Mode = GPIO_MODE_AF_OD;
+    } else {
+        gpio.Mode = GPIO_MODE_AF_PP;
+    }
+    rc = hal_gpio_init_stm(cfg->miso_pin, &gpio);
+    if (rc != 0) {
+        goto err;
+    }
+
     switch (settings->data_mode) {
         case HAL_SPI_MODE0:
             init->CLKPolarity = SPI_POLARITY_LOW;
@@ -536,13 +612,24 @@ hal_spi_config(int spi_num, struct hal_spi_settings 
*settings)
 
     init->BaudRatePrescaler = prescaler;
 
+    irq = stm32f4_resolve_spi_irq(&spi->handle);
+    NVIC_SetPriority(irq, cfg->irq_prio);
+    NVIC_SetVector(irq, stm32f4_resolve_spi_irq_handler(&spi->handle));
+    NVIC_EnableIRQ(irq);
+
     /* Init, Enable */
     rc = HAL_SPI_Init(&spi->handle);
     if (rc != 0) {
         goto err;
     }
-    if (spi->type == HAL_SPI_TYPE_MASTER) {
+    if (!spi->slave) {
         spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
+    } else {
+        rc = hal_gpio_irq_init(cfg->ss_pin, spi_ss_isr, spi, GPIO_TRIG_BOTH,
+          GPIO_PULL_UP);
+        if (hal_gpio_read(cfg->ss_pin) == 0) {
+            spi_ss_isr(spi);
+        }
     }
     return (0);
 err:
@@ -558,11 +645,21 @@ hal_spi_txrx_noblock(int spi_num, void *txbuf, void 
*rxbuf, int len)
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
 
     rc = -1;
-    if (spi->type == HAL_SPI_TYPE_MASTER) {
-        spi->handle.Instance->CR1 |= SPI_CR1_SSI;
-        __HAL_SPI_ENABLE(&spi->handle);
+    if (!spi->slave) {
+        spi->handle.Instance->CR1 |= (SPI_CR1_SSI | SPI_CR1_SPE);
+        rc = HAL_SPI_TransmitReceive_IT(&spi->handle, txbuf, rxbuf, len);
+    } else {
+        spi->tx_in_prog = 1;
+        if (spi->selected) {
+            rc = HAL_SPI_TransmitReceive_IT(&spi->handle, txbuf, rxbuf, len);
+        } else {
+            rc = 0;
+            spi->handle.pTxBuffPtr = txbuf;
+            spi->handle.TxXferSize = len;
+            spi->handle.pRxBuffPtr = rxbuf;
+            spi->handle.RxXferSize  = len;
+        }
     }
-    rc = HAL_SPI_TransmitReceive_IT(&spi->handle, txbuf, rxbuf, len);
 err:
     return (rc);
 }
@@ -579,12 +676,23 @@ hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val)
 {
     struct stm32f4_hal_spi *spi;
     int rc;
+    int i;
 
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
 
-    spi->def_char = val;
-    if (spi->type == HAL_SPI_TYPE_SLAVE) {
-        rc = 0;
+    if (spi->slave) {
+        if (spi->handle.Init.DataSize == SPI_DATASIZE_8BIT) {
+            for (i = 0; i < 4; i++) {
+                ((uint8_t *)spi->def_char)[i] = val;
+            }
+        } else {
+            for (i = 0; i < 2; i++) {
+                ((uint16_t *)spi->def_char)[i] = val;
+            }
+        }
+        if (!spi->tx_in_prog && spi->selected) {
+            spi->handle.Instance->DR = val;
+        }
     } else {
         rc = -1;
     }
@@ -613,7 +721,8 @@ uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
     int len;
 
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
-    if (spi->type == HAL_SPI_TYPE_SLAVE) {
+    if (spi->slave) {
+        retval = -1;
         goto err;
     }
     if (spi->handle.Init.DataSize == SPI_DATASIZE_8BIT) {
@@ -621,13 +730,11 @@ uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
     } else {
         len = sizeof(uint16_t);
     }
-    spi->handle.Instance->CR1 |= SPI_CR1_SSI;
-    __HAL_SPI_ENABLE(&spi->handle);
+    spi->handle.Instance->CR1 |= (SPI_CR1_SSI | SPI_CR1_SPE);
     rc = HAL_SPI_TransmitReceive(&spi->handle,(uint8_t *)&val,
                                  (uint8_t *)&retval, len,
                                  STM32F4_HAL_SPI_TIMEOUT);
-    __HAL_SPI_DISABLE(&spi->handle);
-    spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
+    spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
     if (rc != HAL_OK) {
         retval = 0xFFFF;
     }
@@ -670,16 +777,14 @@ hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int 
len)
         goto err;
     }
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
-    if (spi->type == HAL_SPI_TYPE_SLAVE) {
+    if (spi->slave) {
         goto err;
     }
-    spi->handle.Instance->CR1 |= SPI_CR1_SSI;
-    __HAL_SPI_ENABLE(&spi->handle);
+    spi->handle.Instance->CR1 |= (SPI_CR1_SSI | SPI_CR1_SPE);
     rc = HAL_SPI_TransmitReceive(&spi->handle, (uint8_t *)txbuf,
                                  (uint8_t *)rxbuf, len,
                                  STM32F4_HAL_SPI_TIMEOUT);
-    __HAL_SPI_DISABLE(&spi->handle);
-    spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
+    spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
     if (rc != HAL_OK) {
         rc = -1;
         goto err;
@@ -697,12 +802,12 @@ hal_spi_abort(int spi_num)
 
     rc = 0;
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
-    if (spi->type == HAL_SPI_TYPE_SLAVE) {
+    if (spi->slave) {
         goto err;
     }
+    spi->handle.State = HAL_SPI_STATE_READY;
     __HAL_SPI_DISABLE_IT(&spi->handle, SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR);
-    __HAL_SPI_DISABLE(&spi->handle);
-    spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
+    spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
 err:
     return rc;
 }

Reply via email to