aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2018-01-09 15:39:54 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2018-01-09 15:39:54 +0000
commit7e46dc94aa5d6bad9ff7e449878f64938b2437f1 (patch)
tree70cdbe952a24ebdae5f6ab406d7faa3ba72608c3
parentcafec08d95c1428645e3b2efa59d11a3a5c1d432 (diff)
downloadChibiOS-7e46dc94aa5d6bad9ff7e449878f64938b2437f1.tar.gz
ChibiOS-7e46dc94aa5d6bad9ff7e449878f64938b2437f1.tar.bz2
ChibiOS-7e46dc94aa5d6bad9ff7e449878f64938b2437f1.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11242 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/include/hal_spi.h58
-rw-r--r--os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c175
-rw-r--r--os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h12
-rw-r--r--os/hal/src/hal_spi.c47
-rw-r--r--testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.c20
-rw-r--r--testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.h1
-rwxr-xr-xtesthal/STM32/multi/SPI/main.c54
7 files changed, 326 insertions, 41 deletions
diff --git a/os/hal/include/hal_spi.h b/os/hal/include/hal_spi.h
index 3795bf828..fafc3ce2a 100644
--- a/os/hal/include/hal_spi.h
+++ b/os/hal/include/hal_spi.h
@@ -61,6 +61,14 @@
#endif
/**
+ * @brief Enables circular transfers APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
+#define SPI_USE_CIRCULAR FALSE
+#endif
+
+/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
@@ -106,6 +114,12 @@ typedef enum {
#include "hal_spi_lld.h"
+/* Some more checks, must happen after inclusion of the LLD header, this is
+ why are placed here.*/
+#if !defined(SPI_SUPPORTS_CIRCULAR)
+#define SPI_SUPPORTS_CIRCULAR FALSE
+#endif
+
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
@@ -321,6 +335,46 @@ do { \
(spip)->state = SPI_READY; \
_spi_wakeup_isr(spip); \
}
+
+/**
+ * @brief Common ISR code in circular mode.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_isr_code_half1(spip) { \
+ if ((spip)->config->end_cb) { \
+ (spip)->config->end_cb(spip); \
+ } \
+}
+
+/**
+ * @brief Common ISR code in circular mode.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_isr_code_half2(spip) { \
+ if ((spip)->config->end_cb) { \
+ (spip)->state = SPI_COMPLETE; \
+ (spip)->config->end_cb(spip); \
+ if ((spip)->state == SPI_COMPLETE) \
+ (spip)->state = SPI_ACTIVE; \
+ } \
+}
/** @} */
/*===========================================================================*/
@@ -341,6 +395,10 @@ extern "C" {
const void *txbuf, void *rxbuf);
void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf);
void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf);
+#if SPI_SUPPORTS_CIRCULAR == TRUE
+ void spiAbortI(SPIDriver *spip);
+ void spiAbort(SPIDriver *spip);
+#endif
#if SPI_USE_WAIT == TRUE
void spiIgnore(SPIDriver *spip, size_t n);
void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf);
diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
index dbc9d1f1d..855b931cd 100644
--- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
+++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
@@ -75,42 +75,118 @@ static uint32_t dummyrx;
/* Driver local functions. */
/*===========================================================================*/
+#if defined(STM32_SPI_BDMA_REQUIRED)
/**
- * @brief Shared end-of-rx service routine.
+ * @brief Shared DMA end-of-rx service routine.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
-static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+static void spi_lld_serve_bdma_rx_interrupt(SPIDriver *spip, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_SPI_DMA_ERROR_HOOK)
- if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ if ((flags & STM32_BDMA_ISR_TEIF) != 0U) {
STM32_SPI_DMA_ERROR_HOOK(spip);
}
#else
(void)flags;
#endif
- /* Stopping SPI.*/
- spip->spi->CR1 |= SPI_CR1_CSUSP;
+ if (spip->config->circular) {
+ if ((flags & STM32_BDMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_code_half1(spip);
+ }
+ else {
+ /* End buffer interrupt.*/
+ _spi_isr_code_half2(spip);
+ }
+ }
+ else {
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ /* Stopping DMAs.*/
+ bdmaStreamDisable(spip->tx.bdma);
+ bdmaStreamDisable(spip->rx.bdma);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
+
+/**
+ * @brief Shared BDMA end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_bdma_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & STM32_BDMA_ISR_TEIF) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+#endif /* defined(STM32_SPI_BDMA_REQUIRED) */
+
+#if defined(STM32_SPI_DMA_REQUIRED)
+/**
+ * @brief Shared DMA end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_dma_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
- /* Stop everything.*/
- dmaStreamDisable(spip->tx.dma);
- dmaStreamDisable(spip->rx.dma);
+ if (spip->config->circular) {
+ if ((flags & STM32_DMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_code_half1(spip);
+ }
+ else {
+ /* End buffer interrupt.*/
+ _spi_isr_code_half2(spip);
+ }
+ }
+ else {
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
- /* Portable SPI ISR code defined in the high level driver, note, it is
- a macro.*/
- _spi_isr_code(spip);
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->tx.dma);
+ dmaStreamDisable(spip->rx.dma);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
}
/**
- * @brief Shared end-of-tx service routine.
+ * @brief Shared DMA end-of-tx service routine.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
-static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+static void spi_lld_serve_dma_tx_interrupt(SPIDriver *spip, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_SPI_DMA_ERROR_HOOK)
@@ -123,6 +199,7 @@ static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
(void)flags;
#endif
}
+#endif /* defined(STM32_SPI_DMA_REQUIRED) */
/**
* @brief Shared SPI service routine.
@@ -429,12 +506,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = dmaStreamAllocate(spip->rx.dma,
STM32_SPI_SPI1_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(spip->tx.dma,
STM32_SPI_SPI1_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI1(false);
@@ -447,12 +524,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = dmaStreamAllocate(spip->rx.dma,
STM32_SPI_SPI2_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(spip->tx.dma,
STM32_SPI_SPI2_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI2(false);
@@ -465,12 +542,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = dmaStreamAllocate(spip->rx.dma,
STM32_SPI_SPI3_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(spip->tx.dma,
STM32_SPI_SPI3_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI3(false);
@@ -483,12 +560,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = dmaStreamAllocate(spip->rx.dma,
STM32_SPI_SPI4_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(spip->tx.dma,
STM32_SPI_SPI4_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI4(false);
@@ -501,12 +578,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = dmaStreamAllocate(spip->rx.dma,
STM32_SPI_SPI5_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = dmaStreamAllocate(spip->tx.dma,
STM32_SPI_SPI5_IRQ_PRIORITY,
- (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI5(false);
@@ -519,12 +596,12 @@ void spi_lld_start(SPIDriver *spip) {
bool b;
b = bdmaStreamAllocate(spip->rx.bdma,
STM32_SPI_SPI6_IRQ_PRIORITY,
- (stm32_bdmaisr_t)spi_lld_serve_rx_interrupt,
+ (stm32_bdmaisr_t)spi_lld_serve_bdma_rx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
b = bdmaStreamAllocate(spip->tx.bdma,
STM32_SPI_SPI6_IRQ_PRIORITY,
- (stm32_bdmaisr_t)spi_lld_serve_tx_interrupt,
+ (stm32_bdmaisr_t)spi_lld_serve_bdma_tx_interrupt,
(void *)spip);
osalDbgAssert(!b, "stream already allocated");
rccEnableSPI6(false);
@@ -582,6 +659,14 @@ void spi_lld_start(SPIDriver *spip) {
spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD;
}
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ spip->txdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ }
}
#endif
#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
@@ -610,6 +695,14 @@ void spi_lld_start(SPIDriver *spip) {
spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
}
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
}
#endif
@@ -938,6 +1031,38 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
spip->spi->CR1 |= SPI_CR1_CSTART;
}
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spi_lld_abort(SPIDriver *spip) {
+
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ /* Stopping DMAs.*/
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if(spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamDisable(spip->tx.bdma);
+ bdmaStreamDisable(spip->rx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamDisable(spip->tx.dma);
+ dmaStreamDisable(spip->rx.dma);
+ }
+#endif
+}
/**
* @brief Exchanges one frame using a polled wait.
diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h
index 9b011eae8..052a2c58c 100644
--- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h
+++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h
@@ -32,6 +32,11 @@
/*===========================================================================*/
/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/**
* @name Register helpers not found in ST headers
* @{
*/
@@ -516,6 +521,12 @@ typedef void (*spicallback_t)(SPIDriver *spip);
* @brief Driver configuration structure.
*/
typedef struct {
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Enables the circular buffer mode.
+ */
+ bool circular;
+#endif
/**
* @brief Operation complete callback or @p NULL.
*/
@@ -682,6 +693,7 @@ extern "C" {
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+ void spi_lld_abort(SPIDriver *spip);
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
#ifdef __cplusplus
}
diff --git a/os/hal/src/hal_spi.c b/os/hal/src/hal_spi.c
index a16b61591..da42b5e1d 100644
--- a/os/hal/src/hal_spi.c
+++ b/os/hal/src/hal_spi.c
@@ -263,6 +263,49 @@ void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) {
osalSysUnlock();
}
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @iclass
+ */
+void spiAbortI(SPIDriver *spip) {
+
+ osalDbgCheckClassI();
+
+ osalDbgCheck(spip != NULL);
+ osalDbgAssert((spip->state == SPI_ACTIVE) || (spip->state == SPI_COMPLETE),
+ "invalid state");
+
+ spi_lld_abort(spip);
+ spip->state = SPI_READY;
+#if SPI_USE_WAIT == TRUE
+ osalThreadResumeI(&spip->thread, MSG_OK);
+#endif
+}
+
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiAbort(SPIDriver *spip) {
+
+ osalSysLock();
+ osalDbgAssert((spip->state == SPI_READY) || (spip->state == SPI_ACTIVE),
+ "invalid state");
+ if (spip->state == SPI_ACTIVE) {
+ spiAbortI(spip);
+ osalOsRescheduleS();
+ }
+ osalSysUnlock();
+}
+#endif
+
#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Ignores data on the SPI bus.
@@ -284,7 +327,6 @@ void spiIgnore(SPIDriver *spip, size_t n) {
osalSysLock();
osalDbgAssert(spip->state == SPI_READY, "not ready");
- osalDbgAssert(spip->config->end_cb == NULL, "has callback");
spiStartIgnoreI(spip, n);
(void) osalThreadSuspendS(&spip->thread);
osalSysUnlock();
@@ -316,7 +358,6 @@ void spiExchange(SPIDriver *spip, size_t n,
osalSysLock();
osalDbgAssert(spip->state == SPI_READY, "not ready");
- osalDbgAssert(spip->config->end_cb == NULL, "has callback");
spiStartExchangeI(spip, n, txbuf, rxbuf);
(void) osalThreadSuspendS(&spip->thread);
osalSysUnlock();
@@ -344,7 +385,6 @@ void spiSend(SPIDriver *spip, size_t n, const void *txbuf) {
osalSysLock();
osalDbgAssert(spip->state == SPI_READY, "not ready");
- osalDbgAssert(spip->config->end_cb == NULL, "has callback");
spiStartSendI(spip, n, txbuf);
(void) osalThreadSuspendS(&spip->thread);
osalSysUnlock();
@@ -372,7 +412,6 @@ void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) {
osalSysLock();
osalDbgAssert(spip->state == SPI_READY, "not ready");
- osalDbgAssert(spip->config->end_cb == NULL, "has callback");
spiStartReceiveI(spip, n, rxbuf);
(void) osalThreadSuspendS(&spip->thread);
osalSysUnlock();
diff --git a/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.c b/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.c
index 152b669e8..42caab502 100644
--- a/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.c
+++ b/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.c
@@ -34,10 +34,25 @@
/* Module exported variables. */
/*===========================================================================*/
+void spi_circular_cb(SPIDriver *spip);
+
+/*
+ * Circular SPI configuration (25MHz, CPHA=0, CPOL=0, MSb first).
+ */
+const SPIConfig c_spicfg = {
+ true,
+ spi_circular_cb,
+ GPIOD,
+ GPIOD_SPI1_NSS,
+ SPI_CFG1_MBR_DIV8 | SPI_CFG1_DSIZE_VALUE(7),
+ 0
+};
+
/*
- * Maximum speed SPI configuration (21MHz, CPHA=0, CPOL=0, MSb first).
+ * Maximum speed SPI configuration (25MHz, CPHA=0, CPOL=0, MSb first).
*/
const SPIConfig hs_spicfg = {
+ false,
NULL,
GPIOD,
GPIOD_SPI1_NSS,
@@ -46,9 +61,10 @@ const SPIConfig hs_spicfg = {
};
/*
- * Low speed SPI configuration (328.125kHz, CPHA=0, CPOL=0, MSb first).
+ * Low speed SPI configuration (1.5625MHz, CPHA=0, CPOL=0, MSb first).
*/
const SPIConfig ls_spicfg = {
+ false,
NULL,
GPIOD,
GPIOD_SPI1_NSS,
diff --git a/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.h b/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.h
index 901638a7f..b36241ad9 100644
--- a/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.h
+++ b/testhal/STM32/multi/SPI/cfg-stm32h743_nucleo144/portab.h
@@ -57,6 +57,7 @@
/* External declarations. */
/*===========================================================================*/
+extern const SPIConfig c_spicfg;
extern const SPIConfig hs_spicfg;
extern const SPIConfig ls_spicfg;
diff --git a/testhal/STM32/multi/SPI/main.c b/testhal/STM32/multi/SPI/main.c
index 85328a6a3..d4e5e3e80 100755
--- a/testhal/STM32/multi/SPI/main.c
+++ b/testhal/STM32/multi/SPI/main.c
@@ -26,6 +26,23 @@
CC_ALIGN(32) static uint8_t txbuf[512];
CC_ALIGN(32) static uint8_t rxbuf[512];
+#if SPI_SUPPORTS_CIRCULAR == TRUE
+/*
+ * SPI callback for circular operations.
+ */
+void spi_circular_cb(SPIDriver *spip) {
+
+ if(spip->state == SPI_COMPLETE) {
+ /* 2nd half.*/
+ palWriteLine(PORTAB_LINE_LED1, PORTAB_LED_OFF);
+ }
+ else {
+ /* 1st half.*/
+ palWriteLine(PORTAB_LINE_LED1, PORTAB_LED_ON);
+ }
+}
+#endif
+
/*
* SPI bus contender 1.
*/
@@ -70,7 +87,6 @@ static THD_FUNCTION(spi_thread_2, p) {
}
}
-#if defined(PORTAB_LINE_LED2)
/*
* LED blinker thread, times are in milliseconds.
*/
@@ -79,12 +95,19 @@ static THD_FUNCTION(Thread1, arg) {
(void)arg;
chRegSetThreadName("blinker");
while (true) {
- systime_t time = palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED ? 250 : 500;
+ bool key_pressed = palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED;
+ systime_t time = key_pressed ? 250 : 500;
+#if SPI_SUPPORTS_CIRCULAR == TRUE
+ if (key_pressed) {
+ spiAbort(&PORTAB_SPI1);
+ }
+#endif
+#if defined(PORTAB_LINE_LED2)
palToggleLine(PORTAB_LINE_LED2);
+#endif
chThdSleepMilliseconds(time);
}
}
-#endif
/*
* Application entry point.
@@ -108,12 +131,30 @@ int main(void) {
portab_setup();
/*
+ * Creates the blinker thread.
+ */
+ chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
+
+ /*
* Prepare transmit pattern.
*/
for (i = 0; i < sizeof(txbuf); i++)
txbuf[i] = (uint8_t)i;
cacheBufferFlush(&txbuf[0], sizeof txbuf);
+#if SPI_SUPPORTS_CIRCULAR == TRUE
+ /*
+ * Starting a continous operation for test.
+ */
+ spiStart(&PORTAB_SPI1, &c_spicfg); /* Setup transfer parameters. */
+ spiSelect(&PORTAB_SPI1); /* Slave Select assertion. */
+ spiExchange(&PORTAB_SPI1, 512,
+ txbuf, rxbuf); /* Atomic transfer operations. */
+ spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */
+ cacheBufferInvalidate(&txbuf[0], /* Cache invalidation over the */
+ sizeof txbuf);/* buffer. */
+#endif
+
/*
* Starting the transmitter and receiver threads.
*/
@@ -122,13 +163,6 @@ int main(void) {
chThdCreateStatic(spi_thread_2_wa, sizeof(spi_thread_2_wa),
NORMALPRIO + 1, spi_thread_2, NULL);
-#if defined(PORTAB_LINE_LED2)
- /*
- * Creates the blinker thread.
- */
- chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
-#endif
-
/*
* Normal main() thread activity, in this demo it does nothing.
*/