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;
+}