git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11242 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
cafec08d95
commit
7e46dc94aa
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern const SPIConfig c_spicfg;
|
||||
extern const SPIConfig hs_spicfg;
|
||||
extern const SPIConfig ls_spicfg;
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue