You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/10/18 20:16:16 UTC

[1/5] incubator-mynewt-core git commit: stm32f4 hal spi; fix race when slave saw CS; sometimes was sending first byte twice.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop e238713aa -> d0df2fbd4


stm32f4 hal spi; fix race when slave saw CS; sometimes was sending
first byte twice.


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/d0df2fbd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/d0df2fbd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/d0df2fbd

Branch: refs/heads/develop
Commit: d0df2fbd41454f76408c5ab7637e38099714b015
Parents: d3ed09c
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Oct 18 13:14:32 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Oct 18 13:15:41 2016 -0700

----------------------------------------------------------------------
 hw/mcu/stm/stm32f4xx/src/hal_spi.c | 103 ++++++++++++++++++++++----------
 1 file changed, 73 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0df2fbd/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 c52fae9..4ed3bc0 100644
--- a/hw/mcu/stm/stm32f4xx/src/hal_spi.c
+++ b/hw/mcu/stm/stm32f4xx/src/hal_spi.c
@@ -42,10 +42,10 @@
 
 struct stm32f4_hal_spi {
     SPI_HandleTypeDef handle;
-    uint8_t slave:1;
-    uint8_t tx_in_prog:1;
-    uint8_t selected:1;
-    uint8_t def_char[4];
+    uint8_t slave:1;			/* slave or master */
+    uint8_t tx_in_prog:1;		/* slave: tx'ing user data not def */
+    uint8_t selected:1;			/* slave: if we see SS */
+    uint8_t def_char[4];		/* slave: default data to tx */
     struct stm32f4_hal_spi_cfg *cfg;
     /* Callback and arguments */
     hal_spi_txrx_cb txrx_cb_func;
@@ -155,6 +155,9 @@ stm32f4_resolve_spi_irq(SPI_HandleTypeDef *hspi)
     }
 }
 
+/*
+ * SPI master IRQ handler.
+ */
 static void
 spim_irq_handler(struct stm32f4_hal_spi *spi)
 {
@@ -165,11 +168,17 @@ spim_irq_handler(struct stm32f4_hal_spi *spi)
     }
 }
 
+/*
+ * SPI slave IRQ handler.
+ */
 static void
 spis_irq_handler(struct stm32f4_hal_spi *spi)
 {
     if (spi->tx_in_prog) {
         if (spi->handle.TxXferCount == 0 && spi->handle.RxXferCount == 0) {
+            /*
+             * If finished with data tx, start transmitting default char
+             */
             spi->tx_in_prog = 0;
 
             HAL_SPI_Transmit_IT(&spi->handle, spi->def_char, 2);
@@ -179,11 +188,17 @@ spis_irq_handler(struct stm32f4_hal_spi *spi)
             }
         }
     } else {
+        /*
+         * Reset TX pointer within default data.
+         */
         spi->handle.pTxBuffPtr = spi->def_char;
         spi->handle.TxXferCount = 2;
     }
 }
 
+/*
+ * Common IRQ handler for both master and slave.
+ */
 static void
 spi_irq_handler(struct stm32f4_hal_spi *spi)
 {
@@ -212,51 +227,71 @@ spi_irq_handler(struct stm32f4_hal_spi *spi)
     }
 }
 
+/*
+ * GPIO interrupt when slave gets selected/deselected.
+ */
 static void
 spi_ss_isr(void *arg)
 {
     struct stm32f4_hal_spi *spi = (struct stm32f4_hal_spi *)arg;
     int ss;
     int len;
-    int rc;
     uint16_t reg;
 
     spi_stat.ss_irq++;
     ss = hal_gpio_read(spi->cfg->ss_pin);
     if (ss == 0 && !spi->selected) {
-        reg = spi->handle.Instance->CR1;
-        reg &= ~SPI_CR1_SSI;
-        spi->handle.Instance->CR1 = reg;
+        /*
+         * We're now seeing chip select. Enable SPI, SPI interrupts.
+         */
         if (spi->tx_in_prog) {
-            rc = HAL_SPI_TransmitReceive_IT(&spi->handle,
-              spi->handle.pTxBuffPtr, spi->handle.pRxBuffPtr,
-              spi->handle.TxXferSize);
+            __HAL_SPI_ENABLE_IT(&spi->handle,
+              SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
         } else {
-            rc = HAL_SPI_Transmit_IT(&spi->handle, spi->def_char, 2);
+            __HAL_SPI_ENABLE_IT(&spi->handle, SPI_IT_TXE | SPI_IT_ERR);
         }
-        assert(rc == 0);
+        reg = spi->handle.Instance->CR1;
+        reg &= ~SPI_CR1_SSI;
+        reg |= SPI_CR1_SPE;
+        spi->handle.Instance->CR1 = reg;
         spi->selected = 1;
     }
     if (ss == 1 && spi->selected) {
+        /*
+         * Chip select done. Check whether there's pending data to RX.
+         */
         if (spi->handle.Instance->SR & SPI_SR_RXNE && spi->handle.RxISR) {
             spi->handle.RxISR(&spi->handle);
         }
+
+        /*
+         * Disable SPI.
+         */
         reg = spi->handle.Instance->CR1;
         reg &= ~SPI_CR1_SPE;
         reg |= SPI_CR1_SSI;
+        spi->handle.Instance->CR1 = reg;
 
         __HAL_SPI_DISABLE_IT(&spi->handle, SPI_IT_RXNE|SPI_IT_TXE|SPI_IT_ERR);
 
-        spi->handle.Instance->CR1 = reg;
         len = spi->handle.RxXferSize - spi->handle.RxXferCount;
-        if (spi->tx_in_prog && len) {
-            spi->tx_in_prog = 0;
+        if (len) {
+            /*
+             * If some data was clocked out, reset to start sending
+             * default data and call callback, if user was waiting for
+             * data.
+             */
+            spi->handle.State = HAL_SPI_STATE_READY;
+            HAL_SPI_QueueTransmit(&spi->handle, spi->def_char, 2);
 
-            if (spi->txrx_cb_func) {
-                spi->txrx_cb_func(spi->txrx_cb_arg, len);
+            if (spi->tx_in_prog) {
+                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;
     }
 }
@@ -660,7 +695,7 @@ hal_spi_config(int spi_num, struct hal_spi_settings *settings)
         goto err;
     }
     if (spi->slave) {
-        spi->handle.Instance->CR1 &= ~SPI_CR1_SSI;
+        hal_spi_slave_set_def_tx_val(spi_num, 0);
         rc = hal_gpio_irq_init(cfg->ss_pin, spi_ss_isr, spi, GPIO_TRIG_BOTH,
           GPIO_PULL_UP);
         spi_ss_isr(spi);
@@ -681,22 +716,25 @@ hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int len)
 
     STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
 
-    __HAL_DISABLE_INTERRUPTS(sr);
     spi_stat.tx++;
     rc = -1;
+    __HAL_DISABLE_INTERRUPTS(sr);
     if (!spi->slave) {
         rc = HAL_SPI_TransmitReceive_IT(&spi->handle, txbuf, rxbuf, len);
     } else {
-        spi->tx_in_prog = 1;
+        /*
+         * Slave: if selected, start transmitting new data.
+         * If not selected, queue it for transmission.
+         */
+        spi->handle.State = HAL_SPI_STATE_READY;
         if (spi->selected) {
-            spi->handle.State = HAL_SPI_STATE_READY;
             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_Slave_Queue_TransmitReceive(&spi->handle, txbuf, rxbuf,
+              len);
+        }
+        if (rc == 0) {
+            spi->tx_in_prog = 1;
         }
     }
     __HAL_ENABLE_INTERRUPTS(sr);
@@ -732,8 +770,13 @@ hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val)
                 ((uint16_t *)spi->def_char)[i] = val;
             }
         }
-        if (!spi->tx_in_prog && spi->selected) {
-            spi->handle.Instance->DR = val;
+        if (!spi->tx_in_prog) {
+            /*
+             * Replaces the current default char in tx buffer register.
+             */
+            spi->handle.State = HAL_SPI_STATE_READY;
+            rc = HAL_SPI_QueueTransmit(&spi->handle, spi->def_char, 2);
+            assert(rc == 0);
         }
         __HAL_ENABLE_INTERRUPTS(sr);
     } else {


[4/5] incubator-mynewt-core git commit: stm32f4 gpio; when enabling GPIO output, start driving it with the desired initial state.

Posted by ma...@apache.org.
stm32f4 gpio; when enabling GPIO output, start driving it with
the desired initial state.


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/d3ed09cd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/d3ed09cd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/d3ed09cd

Branch: refs/heads/develop
Commit: d3ed09cd9b1836c67465a0ffa4e6bc63b7cc25ac
Parents: 8ef2522
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Oct 18 12:51:56 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Oct 18 13:15:41 2016 -0700

----------------------------------------------------------------------
 hw/mcu/stm/stm32f4xx/src/hal_gpio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d3ed09cd/hw/mcu/stm/stm32f4xx/src/hal_gpio.c
----------------------------------------------------------------------
diff --git a/hw/mcu/stm/stm32f4xx/src/hal_gpio.c b/hw/mcu/stm/stm32f4xx/src/hal_gpio.c
index 9b19040..1db025e 100644
--- a/hw/mcu/stm/stm32f4xx/src/hal_gpio.c
+++ b/hw/mcu/stm/stm32f4xx/src/hal_gpio.c
@@ -469,11 +469,11 @@ int hal_gpio_init_out(int pin, int val)
     init_cfg.Speed = GPIO_SPEED_HIGH;
     init_cfg.Alternate = 0;
 
+    hal_gpio_write(pin, val);
     rc = hal_gpio_init_stm(pin, &init_cfg);
     if (rc) {
         return rc;
     }
-    hal_gpio_write(pin, val);
     return 0;
 }
 


[2/5] incubator-mynewt-core git commit: stm32f4 SDK; add routines which queue tx/rx without enabling SPI.

Posted by ma...@apache.org.
stm32f4 SDK; add routines which queue tx/rx without enabling SPI.


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/8ef25221
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8ef25221
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8ef25221

Branch: refs/heads/develop
Commit: 8ef252214cbb1972fe7a4e41869d10c012ac186f
Parents: f9dc1be
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Oct 18 12:50:53 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Oct 18 13:15:41 2016 -0700

----------------------------------------------------------------------
 .../Inc/stm32f4xx_hal_spi.h                     |  2 +
 .../Src/stm32f4xx_hal_spi.c                     | 92 +++++++++++++-------
 2 files changed, 63 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ef25221/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h
----------------------------------------------------------------------
diff --git a/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h b/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h
index 5287f63..5176c4f 100644
--- a/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h
+++ b/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h
@@ -442,8 +442,10 @@ HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint
 HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
 HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);
 HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_QueueTransmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
 HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
 HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_Slave_Queue_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);
 HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
 HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
 HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ef25221/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c b/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c
index 84f9597..bdf493c 100644
--- a/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c
+++ b/hw/mcu/stm/stm32f4xx/src/ext/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c
@@ -1040,6 +1040,37 @@ HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, u
   /* Process Locked */
   __HAL_LOCK(hspi);
 
+  errorcode = HAL_SPI_QueueTransmit(hspi, pData, Size);
+  if (errorcode) {
+      goto error;
+  }
+  if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+  {
+    /* Enable TXE interrupt */
+    __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE));
+  }
+  else
+  {
+    /* Enable TXE and ERR interrupt */
+    __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+  }
+
+  /* Check if the SPI is already enabled */
+  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+error :
+  __HAL_UNLOCK(hspi);
+  return errorcode;
+}
+
+HAL_StatusTypeDef HAL_SPI_QueueTransmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+  HAL_StatusTypeDef errorcode = HAL_OK;
+
   if((pData == NULL) || (Size == 0U))
   {
     errorcode = HAL_ERROR;
@@ -1089,29 +1120,11 @@ HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, u
   }
 #endif /* USE_SPI_CRC */
 
-  if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
-  {
-    /* Enable TXE interrupt */
-    __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE));
-  }
-  else
-  {
-    /* Enable TXE and ERR interrupt */
-    __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
-  }
-
   if ((hspi->Instance->CR1 & SPI_CR1_MSTR) == 0) {
       hspi->TxISR(hspi);
   }
-  /* Check if the SPI is already enabled */
-  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
-  {
-    /* Enable SPI peripheral */
-    __HAL_SPI_ENABLE(hspi);
-  }
 
 error :
-  __HAL_UNLOCK(hspi);
   return errorcode;
 }
 
@@ -1217,8 +1230,7 @@ error :
   */
 HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
 {
-  uint32_t tmp = 0U, tmp1 = 0U;
-  HAL_StatusTypeDef errorcode = HAL_OK;
+  HAL_StatusTypeDef errorcode;
 
   /* Check Direction parameter */
   assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
@@ -1226,6 +1238,35 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *p
   /* Process locked */
   __HAL_LOCK(hspi);
 
+  errorcode = HAL_SPI_Slave_Queue_TransmitReceive(hspi, pTxData, pRxData, Size);
+  if (errorcode) {
+      goto error;
+  }
+
+  /* Enable TXE, RXNE and ERR interrupt */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+  /* Check if the SPI is already enabled */
+  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+error:
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+  return errorcode;
+}
+
+HAL_StatusTypeDef HAL_SPI_Slave_Queue_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
+{
+  uint32_t tmp = 0U, tmp1 = 0U;
+  HAL_StatusTypeDef errorcode = HAL_OK;
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
   tmp  = hspi->State;
   tmp1 = hspi->Init.Mode;
   
@@ -1277,22 +1318,11 @@ HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *p
   }
 #endif /* USE_SPI_CRC */
 
-  /* Enable TXE, RXNE and ERR interrupt */
-  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
-
   if ((hspi->Instance->CR1 & SPI_CR1_MSTR) == 0) {
       hspi->TxISR(hspi);
   }
-  /* Check if the SPI is already enabled */
-  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
-  {
-    /* Enable SPI peripheral */
-    __HAL_SPI_ENABLE(hspi);
-  }
 
 error :
-  /* Process Unlocked */
-  __HAL_UNLOCK(hspi);
   return errorcode;
 }
 


[5/5] incubator-mynewt-core git commit: spitest; print received/transmitted bytes.

Posted by ma...@apache.org.
spitest; print received/transmitted bytes.


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/f9dc1bec
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/f9dc1bec
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/f9dc1bec

Branch: refs/heads/develop
Commit: f9dc1becb2af033bc1f4ee3d795798dced4e03d0
Parents: 97bf286
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Oct 18 10:11:09 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Oct 18 13:15:41 2016 -0700

----------------------------------------------------------------------
 apps/spitest/src/main.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f9dc1bec/apps/spitest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/spitest/src/main.c b/apps/spitest/src/main.c
index 0059bc5..9f125ce 100755
--- a/apps/spitest/src/main.c
+++ b/apps/spitest/src/main.c
@@ -26,6 +26,7 @@
 #include <os/os_dev.h>
 #include <assert.h>
 #include <string.h>
+#include <console/console.h>
 #ifdef ARCH_sim
 #include <mcu/mcu_sim.h>
 #endif
@@ -283,6 +284,16 @@ task1_handler(void *arg)
             rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf,
                                       spi_cb_obj.txlen);
             assert(!rc);
+            console_printf("a transmitted: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_tx_buf[i]);
+            }
+            console_printf("\n");
+            console_printf("received: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_rx_buf[i]);
+            }
+            console_printf("\n");
 #endif
         } else {
             /* Send blocking */
@@ -305,6 +316,16 @@ task1_handler(void *arg)
             rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, spi_cb_obj.txlen);
             assert(!rc);
             hal_gpio_set(SPI_SS_PIN);
+            console_printf("b transmitted: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_tx_buf[i]);
+            }
+            console_printf("\n");
+            console_printf("received: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_rx_buf[i]);
+            }
+            console_printf("\n");
             spitest_validate_last(spi_cb_obj.txlen);
 #endif
         }


[3/5] incubator-mynewt-core git commit: stm32f4 hal spi; hw error counters.

Posted by ma...@apache.org.
stm32f4 hal spi; hw error counters.


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/97bf2867
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/97bf2867
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/97bf2867

Branch: refs/heads/develop
Commit: 97bf286714a9d2c6716d226b92bd98518f4e3bbd
Parents: e238713
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Oct 18 10:10:38 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Oct 18 13:15:41 2016 -0700

----------------------------------------------------------------------
 hw/mcu/stm/stm32f4xx/src/hal_spi.c          |  29 +-
 hw/mcu/stm/stm32f4xx/src/hal_spi_soft_ssi.c | 847 +++++++++++++++++++++++
 2 files changed, 873 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/97bf2867/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 c0de992..c52fae9 100644
--- a/hw/mcu/stm/stm32f4xx/src/hal_spi.c
+++ b/hw/mcu/stm/stm32f4xx/src/hal_spi.c
@@ -56,6 +56,9 @@ static struct stm32f4_spi_stat {
     uint32_t irq;
     uint32_t ss_irq;
     uint32_t tx;
+    uint32_t eovf;
+    uint32_t emodf;
+    uint32_t efre;
 } spi_stat;
 
 static void spi_irq_handler(struct stm32f4_hal_spi *spi);
@@ -155,8 +158,6 @@ stm32f4_resolve_spi_irq(SPI_HandleTypeDef *hspi)
 static void
 spim_irq_handler(struct stm32f4_hal_spi *spi)
 {
-    HAL_SPI_IRQHandler(&spi->handle);
-
     if (spi->handle.TxXferCount == 0 && spi->handle.RxXferCount == 0) {
         if (spi->txrx_cb_func) {
             spi->txrx_cb_func(spi->txrx_cb_arg, spi->handle.TxXferSize);
@@ -167,7 +168,6 @@ spim_irq_handler(struct stm32f4_hal_spi *spi)
 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;
@@ -187,7 +187,24 @@ spis_irq_handler(struct stm32f4_hal_spi *spi)
 static void
 spi_irq_handler(struct stm32f4_hal_spi *spi)
 {
+    uint32_t err;
+
     spi_stat.irq++;
+
+    HAL_SPI_IRQHandler(&spi->handle);
+    err = spi->handle.ErrorCode;
+    if (err) {
+        if (err & HAL_SPI_ERROR_OVR) {
+            spi_stat.eovf++;
+        }
+        if (err & HAL_SPI_ERROR_MODF) {
+            spi_stat.emodf++;
+        }
+        if (err & HAL_SPI_ERROR_FRE) {
+            spi_stat.efre++;
+        }
+        spi->handle.ErrorCode = 0;
+    }
     if (!spi->slave) {
         spim_irq_handler(spi);
     } else {
@@ -221,9 +238,15 @@ spi_ss_isr(void *arg)
         spi->selected = 1;
     }
     if (ss == 1 && spi->selected) {
+        if (spi->handle.Instance->SR & SPI_SR_RXNE && spi->handle.RxISR) {
+            spi->handle.RxISR(&spi->handle);
+        }
         reg = spi->handle.Instance->CR1;
         reg &= ~SPI_CR1_SPE;
         reg |= SPI_CR1_SSI;
+
+        __HAL_SPI_DISABLE_IT(&spi->handle, SPI_IT_RXNE|SPI_IT_TXE|SPI_IT_ERR);
+
         spi->handle.Instance->CR1 = reg;
         len = spi->handle.RxXferSize - spi->handle.RxXferCount;
         if (spi->tx_in_prog && len) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/97bf2867/hw/mcu/stm/stm32f4xx/src/hal_spi_soft_ssi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/stm/stm32f4xx/src/hal_spi_soft_ssi.c b/hw/mcu/stm/stm32f4xx/src/hal_spi_soft_ssi.c
new file mode 100644
index 0000000..71bea92
--- /dev/null
+++ b/hw/mcu/stm/stm32f4xx/src/hal_spi_soft_ssi.c
@@ -0,0 +1,847 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <hal/hal_spi.h>
+#include <hal/hal_gpio.h>
+
+#include <string.h>
+
+#include <assert.h>
+
+#include <syscfg/syscfg.h>
+
+#include "stm32f4xx.h"
+#include "stm32f4xx_hal_dma.h"
+#include "stm32f4xx_hal_spi.h"
+#include "stm32f4xx_hal_gpio.h"
+#include "stm32f4xx_hal_gpio_ex.h"
+#include "stm32f4xx_hal_rcc.h"
+#include "mcu/stm32f4xx_mynewt_hal.h"
+#include "mcu/stm32f4_bsp.h"
+#include "bsp/cmsis_nvic.h"
+
+#define STM32F4_HAL_SPI_TIMEOUT (1000)
+
+#define STM32F4_HAL_SPI_MAX (6)
+
+struct stm32f4_hal_spi {
+    SPI_HandleTypeDef handle;
+    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;
+};
+
+static struct stm32f4_spi_stat {
+    uint32_t irq;
+    uint32_t ss_irq;
+} spi_stat;
+
+static void spi_irq_handler(struct stm32f4_hal_spi *spi);
+
+#if MYNEWT_VAL(SPI_0)
+struct stm32f4_hal_spi stm32f4_hal_spi0;
+#endif
+#if MYNEWT_VAL(SPI_1)
+struct stm32f4_hal_spi stm32f4_hal_spi1;
+#endif
+#if MYNEWT_VAL(SPI_2)
+struct stm32f4_hal_spi stm32f4_hal_spi2;
+#endif
+#if MYNEWT_VAL(SPI_3)
+struct stm32f4_hal_spi stm32f4_hal_spi3;
+#endif
+#if MYNEWT_VAL(SPI_4)
+struct stm32f4_hal_spi stm32f4_hal_spi4;
+#endif
+#if MYNEWT_VAL(SPI_5)
+struct stm32f4_hal_spi stm32f4_hal_spi5;
+#endif
+
+static struct stm32f4_hal_spi *stm32f4_hal_spis[STM32F4_HAL_SPI_MAX] = {
+#if MYNEWT_VAL(SPI_0)
+    &stm32f4_hal_spi0,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(SPI_1)
+    &stm32f4_hal_spi1,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(SPI_2)
+    &stm32f4_hal_spi2,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(SPI_3)
+    &stm32f4_hal_spi3,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(SPI_4)
+    &stm32f4_hal_spi4,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(SPI_5)
+    &stm32f4_hal_spi5,
+#else
+    NULL,
+#endif
+};
+
+#define STM32F4_HAL_SPI_RESOLVE(__n, __v)                        \
+    if ((__n) >= STM32F4_HAL_SPI_MAX) {                          \
+        rc = -1;                                                 \
+        goto err;                                                \
+    }                                                            \
+    (__v) = (struct stm32f4_hal_spi *) stm32f4_hal_spis[(__n)];  \
+    if ((__v) == NULL) {                                         \
+        rc = -1;                                                 \
+        goto err;                                                \
+    }
+
+static IRQn_Type
+stm32f4_resolve_spi_irq(SPI_HandleTypeDef *hspi)
+{
+    uintptr_t spi = (uintptr_t)hspi->Instance;
+
+    switch(spi) {
+        case (uintptr_t)SPI1:
+            return SPI1_IRQn;
+        case (uintptr_t)SPI2:
+            return SPI2_IRQn;
+        case (uintptr_t)SPI3:
+            return SPI3_IRQn;
+#ifdef SPI4
+        case (uintptr_t)SPI4:
+            return SPI4_IRQn;
+#endif
+#ifdef SPI5
+        case (uintptr_t)SPI5:
+            return SPI5_IRQn;
+#endif
+#ifdef SPI6
+        case (uintptr_t)SPI6:
+            return SPI6_IRQn;
+#endif
+        default:
+            assert(0);
+    }
+}
+
+static void
+spim_irq_handler(struct stm32f4_hal_spi *spi)
+{
+    HAL_SPI_IRQHandler(&spi->handle);
+
+    if (spi->handle.TxXferCount == 0 && spi->handle.RxXferCount == 0) {
+        spi->handle.Instance->CR1 |= SPI_CR1_SSI;
+        if (spi->txrx_cb_func) {
+            spi->txrx_cb_func(spi->txrx_cb_arg, spi->handle.TxXferSize);
+        }
+    }
+}
+
+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;
+    uint16_t reg;
+
+    spi_stat.ss_irq++;
+    ss = hal_gpio_read(spi->cfg->ss_pin);
+    if (ss == 0 && !spi->selected) {
+        reg = spi->handle.Instance->CR1;
+        reg |= SPI_CR1_SPE;
+        reg &= ~SPI_CR1_SSI;
+        spi->handle.Instance->CR1 = reg;
+        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) {
+        reg = spi->handle.Instance->CR1;
+        reg &= ~SPI_CR1_SPE;
+        reg |= SPI_CR1_SSI;
+        spi->handle.Instance->CR1 = reg;
+        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;
+    }
+}
+
+static void
+spi1_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[0]);
+}
+
+static void
+spi2_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[1]);
+}
+
+static void
+spi3_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[2]);
+}
+
+#ifdef SPI4
+static void
+spi4_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[3]);
+}
+#endif
+
+#ifdef SPI5
+static void
+spi5_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[4]);
+}
+#endif
+
+
+#ifdef SPI6
+static void
+spi6_irq_handler(void)
+{
+    spi_irq_handler(stm32f4_hal_spis[5]);
+}
+#endif
+
+uint32_t
+stm32f4_resolve_spi_irq_handler(SPI_HandleTypeDef *hspi)
+{
+    switch((uintptr_t)hspi->Instance) {
+        case (uintptr_t)SPI1:
+            return (uint32_t)&spi1_irq_handler;
+        case (uintptr_t)SPI2:
+            return (uint32_t)&spi2_irq_handler;
+        case (uintptr_t)SPI3:
+            return (uint32_t)&spi3_irq_handler;
+#ifdef SPI4
+        case (uintptr_t)SPI4:
+            return (uint32_t)&spi4_irq_handler;
+#endif
+#ifdef SPI5
+        case (uintptr_t)SPI5:
+            return (uint32_t)&spi5_irq_handler;
+#endif
+#ifdef SPI6
+        case (uintptr_t)SPI6:
+            return (uint32_t)&spi6_irq_handler;
+#endif
+        default:
+            assert(0);
+    }
+}
+
+int
+hal_spi_init(int spi_num, void *usercfg, uint8_t spi_type)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc;
+
+    /* Check for valid arguments */
+    rc = -1;
+    if (usercfg == NULL) {
+        goto err;
+    }
+
+    if ((spi_type != HAL_SPI_TYPE_MASTER) && (spi_type != HAL_SPI_TYPE_SLAVE)) {
+        goto err;
+    }
+
+    /* Allow user to specify default init settings for the SPI.
+     * This can be done in BSP, so that only the generic SPI settings
+     * are passed to the user configure() call.
+     */
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    spi->cfg = usercfg;
+    spi->slave = (spi_type == HAL_SPI_TYPE_SLAVE);
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+stm32f4_spi_resolve_prescaler(uint8_t spi_num, uint32_t baudrate, uint32_t *prescaler)
+{
+    uint32_t candidate_br;
+    uint32_t apbfreq;
+    int i;
+
+    /* SPIx {1,4,5,6} use PCLK2 on the STM32F4, otherwise use PCKL1.
+     * The numbers in the switch below are offset by 1, because the HALs index
+     * SPI ports from 0.
+     */
+    switch (spi_num) {
+        case 0:
+        case 3:
+        case 4:
+        case 5:
+            apbfreq = HAL_RCC_GetPCLK2Freq();
+            break;
+        default:
+            apbfreq = HAL_RCC_GetPCLK1Freq();
+            break;
+    }
+
+    if (baudrate == 0) {
+        *prescaler = 0;
+        return 0;
+    }
+
+    /* Calculate best-fit prescaler: divide the clock by each subsequent
+     * prescalar until we reach the highest prescalar that generates at
+     * _most_ the baudrate.
+     */
+    *prescaler = SPI_BAUDRATEPRESCALER_256;
+    for (i = 0; i < 8; i++) {
+        candidate_br = apbfreq >> (i + 1);
+        if (candidate_br <= baudrate) {
+            *prescaler = i << 3;
+            break;
+        }
+    }
+
+    return (0);
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc = 0;
+    int sr;
+
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    __HAL_DISABLE_INTERRUPTS(sr);
+    spi->txrx_cb_func = txrx_cb;
+    spi->txrx_cb_arg = arg;
+    __HAL_ENABLE_INTERRUPTS(sr);
+err:
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc;
+
+    rc = 0;
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    /* XXX power up */
+err:
+    return rc;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc;
+
+    rc = 0;
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    if (!spi->slave) {
+        spi->handle.Instance->CR1 |= SPI_CR1_SSI;
+    }
+    /* XXX power down */
+err:
+    return rc;
+}
+
+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;
+    int sr;
+
+    __HAL_DISABLE_INTERRUPTS(sr);
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    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;
+            init->CLKPhase = SPI_PHASE_1EDGE;
+            break;
+        case HAL_SPI_MODE1:
+            init->CLKPolarity = SPI_POLARITY_LOW;
+            init->CLKPhase = SPI_PHASE_2EDGE;
+            break;
+        case HAL_SPI_MODE2:
+            init->CLKPolarity = SPI_POLARITY_HIGH;
+            init->CLKPhase = SPI_PHASE_1EDGE;
+            break;
+        case HAL_SPI_MODE3:
+            init->CLKPolarity = SPI_POLARITY_HIGH;
+            init->CLKPhase = SPI_PHASE_2EDGE;
+            break;
+        default:
+            rc = -1;
+            goto err;
+    }
+
+    switch (settings->data_order) {
+        case HAL_SPI_MSB_FIRST:
+            init->FirstBit = SPI_FIRSTBIT_MSB;
+            break;
+        case HAL_SPI_LSB_FIRST:
+            init->FirstBit = SPI_FIRSTBIT_LSB;
+            break;
+        default:
+            rc = -1;
+            goto err;
+    }
+
+    switch (settings->word_size) {
+        case HAL_SPI_WORD_SIZE_8BIT:
+            init->DataSize = SPI_DATASIZE_8BIT;
+            break;
+        case HAL_SPI_WORD_SIZE_9BIT:
+            init->DataSize = SPI_DATASIZE_16BIT;
+            break;
+        default:
+            rc = -1;
+            goto err;
+    }
+
+    rc = stm32f4_spi_resolve_prescaler(spi_num, settings->baudrate * 1000,
+      &prescaler);
+    if (rc != 0) {
+        goto err;
+    }
+
+    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->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);
+        spi_ss_isr(spi);
+    }
+    __HAL_ENABLE_INTERRUPTS(sr);
+    return (0);
+err:
+    __HAL_ENABLE_INTERRUPTS(sr);
+    return (rc);
+}
+
+int
+hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int len)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc;
+    int sr;
+
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    __HAL_DISABLE_INTERRUPTS(sr);
+    rc = -1;
+    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;
+        }
+    }
+    __HAL_ENABLE_INTERRUPTS(sr);
+err:
+    return (rc);
+}
+
+/**
+ * Sets the default value transferred by the slave. Not valid for master
+ *
+ * @param spi_num SPI interface to use
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val)
+{
+    struct stm32f4_hal_spi *spi;
+    int rc;
+    int sr;
+    int i;
+
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+
+    if (spi->slave) {
+        __HAL_DISABLE_INTERRUPTS(sr);
+        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;
+        }
+        __HAL_ENABLE_INTERRUPTS(sr);
+    } else {
+        rc = -1;
+    }
+err:
+    return rc;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from the
+ * SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    int rc;
+    struct stm32f4_hal_spi *spi;
+    uint16_t retval;
+    uint16_t reg;
+    int len;
+    int sr;
+
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+    if (spi->slave) {
+        retval = -1;
+        goto err;
+    }
+    if (spi->handle.Init.DataSize == SPI_DATASIZE_8BIT) {
+        len = sizeof(uint8_t);
+    } else {
+        len = sizeof(uint16_t);
+    }
+    __HAL_DISABLE_INTERRUPTS(sr);
+    reg = spi->handle.Instance->CR1;
+    reg &= ~SPI_CR1_SSI;
+    reg |= SPI_CR1_SPE;
+    spi->handle.Instance->CR1 = reg;
+    rc = HAL_SPI_TransmitReceive(&spi->handle,(uint8_t *)&val,
+                                 (uint8_t *)&retval, len,
+                                 STM32F4_HAL_SPI_TIMEOUT);
+    reg = spi->handle.Instance->CR1;
+    reg |= SPI_CR1_SSI;
+    reg &= ~SPI_CR1_SPE;
+    spi->handle.Instance->CR1 = reg;
+    __HAL_ENABLE_INTERRUPTS(sr);
+    if (rc != HAL_OK) {
+        retval = 0xFFFF;
+    }
+
+err:
+    return retval;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len)
+{
+    int rc;
+    struct stm32f4_hal_spi *spi;
+    int sr;
+
+    rc = -1;
+    if (!len) {
+        goto err;
+    }
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+    if (spi->slave) {
+        goto err;
+    }
+    __HAL_DISABLE_INTERRUPTS(sr);
+    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);
+    spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
+    __HAL_ENABLE_INTERRUPTS(sr);
+    if (rc != HAL_OK) {
+        rc = -1;
+        goto err;
+    }
+    rc = 0;
+err:
+    return rc;
+}
+
+int
+hal_spi_abort(int spi_num)
+{
+    int rc;
+    struct stm32f4_hal_spi *spi;
+    int sr;
+
+    rc = 0;
+    STM32F4_HAL_SPI_RESOLVE(spi_num, spi);
+    if (spi->slave) {
+        goto err;
+    }
+    __HAL_DISABLE_INTERRUPTS(sr);
+    spi->handle.State = HAL_SPI_STATE_READY;
+    __HAL_SPI_DISABLE_IT(&spi->handle, SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR);
+    spi->handle.Instance->CR1 &= ~(SPI_CR1_SSI | SPI_CR1_SPE);
+    __HAL_ENABLE_INTERRUPTS(sr);
+err:
+    return rc;
+}