diff --git a/os/xhal/codegen/hal_sio.xml b/os/xhal/codegen/hal_sio.xml
index deee7b897..5ad41c054 100644
--- a/os/xhal/codegen/hal_sio.xml
+++ b/os/xhal/codegen/hal_sio.xml
@@ -407,6 +407,10 @@ do {
Type of SIO event flags.
+
+ Type of structure representing a SIO driver.
+
+
Type of structure representing a SIO configuration.
diff --git a/os/xhal/codegen/hal_spi.xml b/os/xhal/codegen/hal_spi.xml
index 92055e429..f71081955 100644
--- a/os/xhal/codegen/hal_spi.xml
+++ b/os/xhal/codegen/hal_spi.xml
@@ -64,6 +64,10 @@
+
+ Type of structure representing a SPI driver.
+
+
Type of structure representing a SPI configuration.
diff --git a/os/xhal/hal.mk b/os/xhal/hal.mk
index e1c8c30e8..71dd552cc 100644
--- a/os/xhal/hal.mk
+++ b/os/xhal/hal.mk
@@ -34,7 +34,7 @@ HALSRC = $(CHIBIOS)/os/xhal/src/hal.c \
$(CHIBIOS)/os/xhal/src/hal_st.c \
$(CHIBIOS)/os/xhal/src/hal_queues.c \
$(CHIBIOS)/os/xhal/src/hal_pal.c \
- $(CHIBIOS)/os/xhal/src/hal_sio.c
+ $(CHIBIOS)/os/xhal/src/hal_sio.c \
$(CHIBIOS)/os/xhal/src/hal_spi.c
endif
diff --git a/os/xhal/include/hal_sio.h b/os/xhal/include/hal_sio.h
index 145f632b3..4a8e08788 100644
--- a/os/xhal/include/hal_sio.h
+++ b/os/xhal/include/hal_sio.h
@@ -477,6 +477,11 @@
*/
typedef chnflags_t sioevents_t;
+/**
+ * @brief Type of structure representing a SIO driver.
+ */
+typedef struct hal_sio_driver hal_sio_driver_c;
+
/**
* @brief Type of structure representing a SIO configuration.
*/
diff --git a/os/xhal/include/hal_spi.h b/os/xhal/include/hal_spi.h
index 2507c45b0..ff2101061 100644
--- a/os/xhal/include/hal_spi.h
+++ b/os/xhal/include/hal_spi.h
@@ -140,6 +140,11 @@
/* Module data structures and types. */
/*===========================================================================*/
+/**
+ * @brief Type of structure representing a SPI driver.
+ */
+typedef struct hal_spi_driver hal_spi_driver_c;
+
/**
* @brief Type of structure representing a SPI configuration.
*/
diff --git a/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.c b/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
index 20c0953f3..f07fcba7b 100644
--- a/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
+++ b/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
@@ -116,6 +116,25 @@ SPIDriver SPID6;
/* Driver local variables and types. */
/*===========================================================================*/
+/*
+ * Default SPI configuration.
+ */
+static const hal_spi_config_t spi_default_config = {
+ .circular = false,
+ .slave = false,
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LINE) || defined (__DOXYGEN__)
+ .ssline = PAL_LINE(STM32_SPI_DEFAULT_PORT, STM32_SPI_DEFAULT_PAD);
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PORT
+ .ssport = STM32_SPI_DEFAULT_PORT,
+ .ssport = PAL_PORT_BIT(STM32_SPI_DEFAULT_PAD),
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
+ .ssport = STM32_SPI_DEFAULT_PORT,
+ .sspad = STM32_SPI_DEFAULT_PAD,
+#endif
+ .cr1 = STM32_SPI_DEFAULT_CR1,
+ .cr2 = STM32_SPI_DEFAULT_CR2
+};
+
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
@@ -454,138 +473,224 @@ void spi_lld_init(void) {
* @notapi
*/
msg_t spi_lld_start(SPIDriver *spip) {
- uint32_t ds;
msg_t msg;
/* Resetting TX pattern source.*/
spip->txsource = (uint32_t)STM32_SPI_FILLER_PATTERN;
- /* If in stopped state then enables the SPI and DMA clocks.*/
- if (spip->state == DRV_STATE_STOP) {
- if (false) {
- }
+ /* Activating SPI unit.*/
+ if (false) {
+ }
#if STM32_SPI_USE_SPI1
- else if (&SPID1 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI1_RX_DMA_STREAM,
- STM32_SPI_SPI1_TX_DMA_STREAM,
- STM32_SPI_SPI1_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI1(true);
- rccResetSPI1();
-#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX);
-#endif
+ else if (&SPID1 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI1_RX_DMA_STREAM,
+ STM32_SPI_SPI1_TX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
}
+ rccEnableSPI1(true);
+ rccResetSPI1();
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX);
+#endif
+ }
#endif
#if STM32_SPI_USE_SPI2
- else if (&SPID2 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI2_RX_DMA_STREAM,
- STM32_SPI_SPI2_TX_DMA_STREAM,
- STM32_SPI_SPI2_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI2(true);
- rccResetSPI2();
-#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX);
-#endif
+ else if (&SPID2 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI2_RX_DMA_STREAM,
+ STM32_SPI_SPI2_TX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
}
+ rccEnableSPI2(true);
+ rccResetSPI2();
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX);
+#endif
+ }
#endif
#if STM32_SPI_USE_SPI3
- else if (&SPID3 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI3_RX_DMA_STREAM,
- STM32_SPI_SPI3_TX_DMA_STREAM,
- STM32_SPI_SPI3_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI3(true);
- rccResetSPI3();
-#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX);
-#endif
+ else if (&SPID3 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI3_RX_DMA_STREAM,
+ STM32_SPI_SPI3_TX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
}
+ rccEnableSPI3(true);
+ rccResetSPI3();
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX);
+#endif
+ }
#endif
#if STM32_SPI_USE_SPI4
- else if (&SPID4 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI4_RX_DMA_STREAM,
- STM32_SPI_SPI4_TX_DMA_STREAM,
- STM32_SPI_SPI4_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI4(true);
- rccResetSPI4();
-#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX);
-#endif
+ else if (&SPID4 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI4_RX_DMA_STREAM,
+ STM32_SPI_SPI4_TX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
}
+ rccEnableSPI4(true);
+ rccResetSPI4();
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX);
+#endif
+ }
#endif
#if STM32_SPI_USE_SPI5
- else if (&SPID5 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI5_RX_DMA_STREAM,
- STM32_SPI_SPI5_TX_DMA_STREAM,
- STM32_SPI_SPI5_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI5(true);
- rccResetSPI5();
-#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX);
-#endif
+ else if (&SPID5 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI5_RX_DMA_STREAM,
+ STM32_SPI_SPI5_TX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
}
+ rccEnableSPI5(true);
+ rccResetSPI5();
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX);
+#endif
+ }
#endif
#if STM32_SPI_USE_SPI6
- else if (&SPID6 == spip) {
- msg = spi_lld_get_dma(spip,
- STM32_SPI_SPI6_RX_DMA_STREAM,
- STM32_SPI_SPI6_TX_DMA_STREAM,
- STM32_SPI_SPI6_IRQ_PRIORITY);
- if (msg != HAL_RET_SUCCESS) {
- return msg;
- }
- rccEnableSPI6(true);
- rccResetSPI6();
+ else if (&SPID6 == spip) {
+ msg = spi_lld_get_dma(spip,
+ STM32_SPI_SPI6_RX_DMA_STREAM,
+ STM32_SPI_SPI6_TX_DMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY);
+ if (msg != HAL_RET_SUCCESS) {
+ return msg;
+ }
+ rccEnableSPI6(true);
+ rccResetSPI6();
#if STM32_DMA_SUPPORTS_DMAMUX
- dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX);
- dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX);
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX);
#endif
- }
-#endif
-
- else {
- osalDbgAssert(false, "invalid SPI instance");
- }
-
- /* DMA setup.*/
- dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR);
- dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR);
}
+#endif
+
else {
- /* De-activation before re-configuration.*/
- spi_lld_disable(spip);
+ osalDbgAssert(false, "invalid SPI instance");
}
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR);
+ dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR);
+
+ /* Configures the peripheral.*/
+ spi_lld_configure(spip, &spi_default_config);
+
+ return HAL_RET_SUCCESS;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ /* Just in case this has been called uncleanly.*/
+ spi_lld_disable(spip);
+
+ /* SPI cleanup.*/
+ spip->spi->CR1 = 0;
+ spip->spi->CR2 = 0;
+
+ /* DMA channels release.*/
+ dmaStreamFreeI(spip->dmatx);
+ dmaStreamFreeI(spip->dmarx);
+ spip->dmarx = NULL;
+ spip->dmatx = NULL;
+
+ /* Clock shutdown.*/
+ if (false) {
+ }
+
+#if STM32_SPI_USE_SPI1
+ else if (&SPID1 == spip) {
+ rccDisableSPI1();
+ }
+#endif
+
+#if STM32_SPI_USE_SPI2
+ else if (&SPID2 == spip) {
+ rccDisableSPI2();
+ }
+#endif
+
+#if STM32_SPI_USE_SPI3
+ else if (&SPID3 == spip) {
+ rccDisableSPI3();
+ }
+#endif
+
+#if STM32_SPI_USE_SPI4
+ else if (&SPID4 == spip) {
+ rccDisableSPI4();
+ }
+#endif
+
+#if STM32_SPI_USE_SPI5
+ else if (&SPID5 == spip) {
+ rccDisableSPI5();
+ }
+#endif
+
+#if STM32_SPI_USE_SPI6
+ else if (&SPID6 == spip) {
+ rccDisableSPI6();
+ }
+#endif
+
+ else {
+ osalDbgAssert(false, "invalid SPI instance");
+ }
+}
+
+/**
+ * @brief SPI configuration.
+ *
+ * @param[in] spip pointer to the @p hal_spi_driver_c object
+ * @param[in] config pointer to the @p hal_spi_config_t structure
+ * @return A pointer to the current configuration structure.
+ *
+ * @notapi
+ */
+const hal_spi_config_t *spi_lld_configure(hal_spi_driver_c *spip,
+ const hal_spi_config_t *config) {
+ uint32_t ds;
+
+ if (config == NULL) {
+ config = &spi_default_config;
+ }
+
+ /* De-activation before re-configuration.*/
+ spi_lld_disable(spip);
+
/* Configuration-specific DMA setup.*/
ds = __spi_getfield(spip, cr2) & SPI_CR2_DS;
if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) {
@@ -615,78 +720,7 @@ msg_t spi_lld_start(SPIDriver *spip) {
/* SPI setup.*/
spi_lld_enable(spip);
- return HAL_RET_SUCCESS;
-}
-
-/**
- * @brief Deactivates the SPI peripheral.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- *
- * @notapi
- */
-void spi_lld_stop(SPIDriver *spip) {
-
- /* If in ready state then disables the SPI clock.*/
- if (spip->state == SPI_READY) {
-
- /* Just in case this has been called uncleanly.*/
- spi_lld_disable(spip);
-
- /* SPI cleanup.*/
- spip->spi->CR1 = 0;
- spip->spi->CR2 = 0;
-
- /* DMA channels release.*/
- dmaStreamFreeI(spip->dmatx);
- dmaStreamFreeI(spip->dmarx);
- spip->dmarx = NULL;
- spip->dmatx = NULL;
-
- /* Clock shutdown.*/
- if (false) {
- }
-
-#if STM32_SPI_USE_SPI1
- else if (&SPID1 == spip) {
- rccDisableSPI1();
- }
-#endif
-
-#if STM32_SPI_USE_SPI2
- else if (&SPID2 == spip) {
- rccDisableSPI2();
- }
-#endif
-
-#if STM32_SPI_USE_SPI3
- else if (&SPID3 == spip) {
- rccDisableSPI3();
- }
-#endif
-
-#if STM32_SPI_USE_SPI4
- else if (&SPID4 == spip) {
- rccDisableSPI4();
- }
-#endif
-
-#if STM32_SPI_USE_SPI5
- else if (&SPID5 == spip) {
- rccDisableSPI5();
- }
-#endif
-
-#if STM32_SPI_USE_SPI6
- else if (&SPID6 == spip) {
- rccDisableSPI6();
- }
-#endif
-
- else {
- osalDbgAssert(false, "invalid SPI instance");
- }
- }
+ return config;
}
#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
diff --git a/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.h b/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.h
index 5923f0d97..c4552ea20 100644
--- a/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.h
+++ b/os/xhal/ports/STM32/LLD/SPIv2/hal_spi_lld.h
@@ -218,6 +218,34 @@
#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
#endif
+
+/**
+ * @brief Default PAL port for Chip Select line.
+ */
+#if !defined(STM32_SPI_DEFAULT_PORT) || defined(__DOXYGEN__)
+#define STM32_SPI_DEFAULT_PORT GPIOA
+#endif
+
+/**
+ * @brief Default PAL pad for Chip Select line.
+ */
+#if !defined(STM32_SPI_DEFAULT_PAD) || defined(__DOXYGEN__)
+#define STM32_SPI_DEFAULT_PAD 0U
+#endif
+
+/**
+ * @brief CR1 setting for default SPI configuration.
+ */
+#if !defined(STM32_SPI_DEFAULT_CR1) || defined(__DOXYGEN__)
+#define STM32_SPI_DEFAULT_CR1 (SPI_CR1_BR_2 | SPI_CR1_BR_1)
+#endif
+
+/**
+ * @brief CR2 setting for default SPI configuration.
+ */
+#if !defined(STM32_SPI_DEFAULT_CR2) || defined(__DOXYGEN__)
+#define STM32_SPI_DEFAULT_CR2 (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0)
+#endif
/** @} */
/*===========================================================================*/
@@ -549,6 +577,8 @@ extern "C" {
void spi_lld_init(void);
msg_t spi_lld_start(SPIDriver *spip);
void spi_lld_stop(SPIDriver *spip);
+ const hal_spi_config_t *spi_lld_configure(hal_spi_driver_c *spip,
+ const hal_spi_config_t *config);
#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
diff --git a/os/xhal/ports/STM32/LLD/USARTv3/hal_sio_lld.c b/os/xhal/ports/STM32/LLD/USARTv3/hal_sio_lld.c
index a9904b7ae..632c80a62 100644
--- a/os/xhal/ports/STM32/LLD/USARTv3/hal_sio_lld.c
+++ b/os/xhal/ports/STM32/LLD/USARTv3/hal_sio_lld.c
@@ -460,6 +460,15 @@ void sio_lld_stop(SIODriver *siop) {
}
}
+/**
+ * @brief SIO configuration.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] config pointer to the @p SIOConfig structure
+ * @return A pointer to the current configuration structure.
+ *
+ * @notapi
+ */
const SIOConfig *sio_lld_configure(SIODriver *siop, const SIOConfig *config) {
USART_TypeDef *u = siop->usart;
uint32_t presc, brr, clock;