From 7e46dc94aa5d6bad9ff7e449878f64938b2437f1 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 9 Jan 2018 15:39:54 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11242 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/hal_spi.h | 58 ++++++ os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c | 175 +++++++++++++++--- os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h | 12 ++ os/hal/src/hal_spi.c | 47 ++++- .../SPI/cfg-stm32h743_nucleo144/portab.c | 20 +- .../SPI/cfg-stm32h743_nucleo144/portab.h | 1 + testhal/STM32/multi/SPI/main.c | 54 +++++- 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 @@ -60,6 +60,14 @@ #define SPI_USE_WAIT TRUE #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; - /* Stop everything.*/ - dmaStreamDisable(spip->tx.dma); - dmaStreamDisable(spip->rx.dma); + /* 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); + /* 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 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_tx_interrupt(SPIDriver *spip, uint32_t flags) { +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 + + 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; + + /* 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 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_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 @@ -31,6 +31,11 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @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); + /* - * Maximum speed SPI configuration (21MHz, CPHA=0, CPOL=0, MSb first). + * 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 (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. @@ -107,6 +130,11 @@ int main(void) { */ portab_setup(); + /* + * Creates the blinker thread. + */ + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + /* * Prepare transmit pattern. */ @@ -114,6 +142,19 @@ int main(void) { 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. */