STM32 related improvements, better SPI driver, improved DMA infrastructure.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2122 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
2d1ded91fe
commit
1c64ee6921
|
@ -53,9 +53,6 @@ SPIDriver SPID3;
|
|||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static uint16_t dummyrx;
|
||||
static uint16_t dummytx;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
@ -63,8 +60,8 @@ static uint16_t dummytx;
|
|||
static void spi_stop(SPIDriver *spip) {
|
||||
|
||||
/* Stops RX and TX DMA channels.*/
|
||||
spip->spd_dmarx->CCR = 0;
|
||||
spip->spd_dmatx->CCR = 0;
|
||||
dmaChannelDisable(spip->spd_dmarx);
|
||||
dmaChannelDisable(spip->spd_dmatx);
|
||||
|
||||
/* Stops SPI operations.*/
|
||||
spip->spd_spi->CR1 &= ~SPI_CR1_SPE;
|
||||
|
@ -74,32 +71,16 @@ static void spi_stop(SPIDriver *spip) {
|
|||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
static void spi_start_wait(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
uint32_t ccr;
|
||||
static void spi_start_wait(SPIDriver *spip) {
|
||||
|
||||
/* Common DMA setup.*/
|
||||
ccr = spip->spd_dmaprio;
|
||||
if ((spip->spd_config->spc_cr1 & SPI_CR1_DFF) != 0)
|
||||
ccr |= DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0; /* 16 bits transfer.*/
|
||||
|
||||
/* RX DMA setup.*/
|
||||
spip->spd_dmarx->CMAR = (uint32_t)rxbuf;
|
||||
spip->spd_dmarx->CNDTR = (uint32_t)n;
|
||||
spip->spd_dmarx->CCR |= ccr;
|
||||
|
||||
/* TX DMA setup.*/
|
||||
spip->spd_dmatx->CMAR = (uint32_t)txbuf;
|
||||
spip->spd_dmatx->CNDTR = (uint32_t)n;
|
||||
spip->spd_dmatx->CCR |= ccr;
|
||||
|
||||
/* SPI enable.*/
|
||||
chSysLock();
|
||||
spip->spd_spi->CR1 |= SPI_CR1_SPE;
|
||||
|
||||
/* DMAs start.*/
|
||||
spip->spd_dmarx->CCR |= DMA_CCR1_EN;
|
||||
spip->spd_dmatx->CCR |= DMA_CCR1_EN;
|
||||
dmaChannelEnable(spip->spd_dmarx);
|
||||
dmaChannelEnable(spip->spd_dmatx);
|
||||
|
||||
/* SPI enable.*/
|
||||
spip->spd_spi->CR1 |= SPI_CR1_SPE;
|
||||
|
||||
/* Wait for completion event.*/
|
||||
spip->spd_thread = currp;
|
||||
|
@ -121,11 +102,10 @@ CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_stop(&SPID1);
|
||||
if ((DMA1->ISR & DMA_ISR_TEIF2) != 0) {
|
||||
if ((STM32_DMA1->ISR & DMA_ISR_TEIF2) != 0) {
|
||||
STM32_SPI_SPI1_DMA_ERROR_HOOK();
|
||||
}
|
||||
DMA1->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 |
|
||||
DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2;
|
||||
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -138,8 +118,7 @@ CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
STM32_SPI_SPI1_DMA_ERROR_HOOK();
|
||||
DMA1->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTCIF3 |
|
||||
DMA_IFCR_CHTIF3 | DMA_IFCR_CTEIF3;
|
||||
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -154,11 +133,10 @@ CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_stop(&SPID2);
|
||||
if ((DMA1->ISR & DMA_ISR_TEIF4) != 0) {
|
||||
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) {
|
||||
STM32_SPI_SPI2_DMA_ERROR_HOOK();
|
||||
}
|
||||
DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 |
|
||||
DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4;
|
||||
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -171,8 +149,7 @@ CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
STM32_SPI_SPI2_DMA_ERROR_HOOK();
|
||||
DMA1->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 |
|
||||
DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5;
|
||||
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -187,11 +164,10 @@ CH_IRQ_HANDLER(DMA2_Ch1_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_stop(&SPID3);
|
||||
if ((DMA2->ISR & DMA_ISR_TEIF1) != 0) {
|
||||
if ((STM32_DMA2->ISR & DMA_ISR_TEIF1) != 0) {
|
||||
STM32_SPI_SPI3_DMA_ERROR_HOOK();
|
||||
}
|
||||
DMA2->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 |
|
||||
DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1;
|
||||
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -204,8 +180,7 @@ CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
STM32_SPI_SPI3_DMA_ERROR_HOOK();
|
||||
DMA2->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 |
|
||||
DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2;
|
||||
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -220,17 +195,14 @@ CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) {
|
|||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
dummytx = 0xFFFF;
|
||||
|
||||
#if STM32_SPI_USE_SPI1
|
||||
RCC->APB2RSTR = RCC_APB2RSTR_SPI1RST;
|
||||
RCC->APB2RSTR = 0;
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.spd_thread = NULL;
|
||||
SPID1.spd_spi = SPI1;
|
||||
SPID1.spd_dmarx = DMA1_Channel2;
|
||||
SPID1.spd_dmatx = DMA1_Channel3;
|
||||
SPID1.spd_dmaprio = STM32_SPI_SPI1_DMA_PRIORITY << 12;
|
||||
SPID1.spd_dmarx = STM32_DMA1_CH2;
|
||||
SPID1.spd_dmatx = STM32_DMA1_CH3;
|
||||
#endif
|
||||
|
||||
#if STM32_SPI_USE_SPI2
|
||||
|
@ -239,9 +211,8 @@ void spi_lld_init(void) {
|
|||
spiObjectInit(&SPID2);
|
||||
SPID2.spd_thread = NULL;
|
||||
SPID2.spd_spi = SPI2;
|
||||
SPID2.spd_dmarx = DMA1_Channel4;
|
||||
SPID2.spd_dmatx = DMA1_Channel5;
|
||||
SPID2.spd_dmaprio = STM32_SPI_SPI2_DMA_PRIORITY << 12;
|
||||
SPID2.spd_dmarx = STM32_DMA1_CH4;
|
||||
SPID2.spd_dmatx = STM32_DMA1_CH5;
|
||||
#endif
|
||||
|
||||
#if STM32_SPI_USE_SPI3
|
||||
|
@ -250,9 +221,8 @@ void spi_lld_init(void) {
|
|||
spiObjectInit(&SPID3);
|
||||
SPID3.spd_thread = NULL;
|
||||
SPID3.spd_spi = SPI3;
|
||||
SPID3.spd_dmarx = DMA2_Channel1;
|
||||
SPID3.spd_dmatx = DMA2_Channel2;
|
||||
SPID3.spd_dmaprio = STM32_SPI_SPI3_DMA_PRIORITY << 12;
|
||||
SPID3.spd_dmarx = STM32_DMA2_CH1;
|
||||
SPID3.spd_dmatx = STM32_DMA2_CH2;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -297,10 +267,19 @@ void spi_lld_start(SPIDriver *spip) {
|
|||
#endif
|
||||
|
||||
/* DMA setup.*/
|
||||
spip->spd_dmarx->CPAR = (uint32_t)&spip->spd_spi->DR;
|
||||
spip->spd_dmatx->CPAR = (uint32_t)&spip->spd_spi->DR;
|
||||
dmaChannelSetPeripheral(spip->spd_dmarx, &spip->spd_spi->DR);
|
||||
dmaChannelSetPeripheral(spip->spd_dmatx, &spip->spd_spi->DR);
|
||||
}
|
||||
|
||||
/* More DMA setup.*/
|
||||
if ((spip->spd_config->spc_cr1 & SPI_CR1_DFF) == 0)
|
||||
spip->spd_dmaccr = (STM32_SPI_SPI2_DMA_PRIORITY << 12) |
|
||||
DMA_CCR1_TEIE; /* 8 bits transfers. */
|
||||
else
|
||||
spip->spd_dmaccr = (STM32_SPI_SPI2_DMA_PRIORITY << 12) |
|
||||
DMA_CCR1_TEIE | DMA_CCR1_MSIZE_0 |
|
||||
DMA_CCR1_PSIZE_0; /* 16 bits transfers. */
|
||||
|
||||
/* SPI setup.*/
|
||||
spip->spd_spi->CR1 = spip->spd_config->spc_cr1 | SPI_CR1_MSTR;
|
||||
spip->spd_spi->CR2 = SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN;
|
||||
|
@ -373,10 +352,14 @@ void spi_lld_unselect(SPIDriver *spip) {
|
|||
* @param[in] n number of words to be ignored
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
uint16_t dummyrx;
|
||||
uint16_t dummytx = 0xFFFF;
|
||||
|
||||
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_TEIE;
|
||||
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_TEIE;
|
||||
spi_start_wait(spip, n, &dummytx, &dummyrx);
|
||||
dmaChannelSetup(spip->spd_dmarx, n, &dummyrx,
|
||||
spip->spd_dmaccr | DMA_CCR1_TCIE);
|
||||
dmaChannelSetup(spip->spd_dmatx, n, &dummytx,
|
||||
spip->spd_dmaccr | DMA_CCR1_DIR);
|
||||
spi_start_wait(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -393,9 +376,11 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
|||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
|
||||
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_MINC | DMA_CCR1_TEIE;
|
||||
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_MINC | DMA_CCR1_TEIE;
|
||||
spi_start_wait(spip, n, txbuf, rxbuf);
|
||||
dmaChannelSetup(spip->spd_dmarx, n, rxbuf,
|
||||
spip->spd_dmaccr | DMA_CCR1_TCIE | DMA_CCR1_MINC);
|
||||
dmaChannelSetup(spip->spd_dmatx, n, txbuf,
|
||||
spip->spd_dmaccr | DMA_CCR1_DIR | DMA_CCR1_MINC);
|
||||
spi_start_wait(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,10 +393,13 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
|
|||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
uint16_t dummyrx;
|
||||
|
||||
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_TEIE;
|
||||
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_MINC | DMA_CCR1_TEIE;
|
||||
spi_start_wait(spip, n, txbuf, &dummyrx);
|
||||
dmaChannelSetup(spip->spd_dmarx, n, &dummyrx,
|
||||
spip->spd_dmaccr | DMA_CCR1_TCIE);
|
||||
dmaChannelSetup(spip->spd_dmatx, n, txbuf,
|
||||
spip->spd_dmaccr | DMA_CCR1_DIR | DMA_CCR1_MINC);
|
||||
spi_start_wait(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,10 +412,13 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
|||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
uint16_t dummytx = 0xFFFF;
|
||||
|
||||
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_MINC | DMA_CCR1_TEIE;
|
||||
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_TEIE;
|
||||
spi_start_wait(spip, n, &dummytx, rxbuf);
|
||||
dmaChannelSetup(spip->spd_dmarx, n, rxbuf,
|
||||
spip->spd_dmaccr | DMA_CCR1_TCIE | DMA_CCR1_MINC);
|
||||
dmaChannelSetup(spip->spd_dmatx, n, &dummytx,
|
||||
spip->spd_dmaccr | DMA_CCR1_DIR);
|
||||
spi_start_wait(spip);
|
||||
}
|
||||
|
||||
#endif /* CH_HAL_USE_SPI */
|
||||
|
|
|
@ -194,11 +194,11 @@ typedef struct {
|
|||
/** @brief Pointer to the SPIx registers block.*/
|
||||
SPI_TypeDef *spd_spi;
|
||||
/** @brief Pointer to the receive DMA channel registers block.*/
|
||||
DMA_Channel_TypeDef *spd_dmarx;
|
||||
stm32_dma_channel_t *spd_dmarx;
|
||||
/** @brief Pointer to the transmit DMA channel registers block.*/
|
||||
DMA_Channel_TypeDef *spd_dmatx;
|
||||
stm32_dma_channel_t *spd_dmatx;
|
||||
/** @brief DMA priority bit mask.*/
|
||||
uint32_t spd_dmaprio;
|
||||
uint32_t spd_dmaccr;
|
||||
} SPIDriver;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -56,10 +56,17 @@ static cnt_t dmacnt2;
|
|||
* @brief STM32 DMA helper initialization.
|
||||
*/
|
||||
void dmaInit(void) {
|
||||
int i;
|
||||
|
||||
dmacnt1 = 0;
|
||||
for (i = STM32_DMA_CHANNEL_7; i >= STM32_DMA_CHANNEL_1; i--)
|
||||
dmaDisableChannel(STM32_DMA1, i);
|
||||
STM32_DMA1->IFCR = 0xFFFFFFFF;
|
||||
#if defined(STM32F10X_HD) || defined (STM32F10X_CL)
|
||||
dmacnt2 = 0;
|
||||
for (i = STM32_DMA_CHANNEL_5; i >= STM32_DMA_CHANNEL_1; i--)
|
||||
dmaDisableChannel(STM32_DMA2, i);
|
||||
STM32_DMA1->IFCR = 0xFFFFFFFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,53 @@ typedef struct {
|
|||
#define STM32_DMA_CHANNEL_7 6 /**< @brief DMA channel 7. */
|
||||
|
||||
/**
|
||||
* @brief DMA channel setup.
|
||||
* @brief Associates a peripheral data register to a DMA channel.
|
||||
*
|
||||
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
|
||||
* @param[in] cmar value to be written in the CPAR register
|
||||
*/
|
||||
#define dmaChannelSetPeripheral(dmachp, cpar) { \
|
||||
(dmachp)->CPAR = (uint32_t)(cpar); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel setup by channel pointer.
|
||||
* @note This macro does not change the CPAR register because that register
|
||||
* value does not change frequently, it usually points to a peripheral
|
||||
* data register.
|
||||
*
|
||||
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
|
||||
* @param[in] cndtr value to be written in the CNDTR register
|
||||
* @param[in] cmar value to be written in the CMAR register
|
||||
* @param[in] ccr value to be written in the CCR register
|
||||
*/
|
||||
#define dmaChannelSetup(dmachp, cndtr, cmar, ccr) { \
|
||||
(dmachp)->CNDTR = (uint32_t)(cndtr); \
|
||||
(dmachp)->CMAR = (uint32_t)(cmar); \
|
||||
(dmachp)->CCR = (uint32_t)(ccr); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable by channel pointer.
|
||||
*
|
||||
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
|
||||
*/
|
||||
#define dmaChannelEnable(dmachp) { \
|
||||
(dmachp)->CCR |= DMA_CCR1_EN; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable by channel pointer.
|
||||
*
|
||||
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
|
||||
*/
|
||||
#define dmaChannelDisable(dmachp) { \
|
||||
(dmachp)->CCR = 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel setup by channel ID.
|
||||
* @note This macro does not change the CPAR register because that register
|
||||
* value does not change frequently, it usually points to a peripheral
|
||||
* data register.
|
||||
|
@ -140,14 +186,11 @@ typedef struct {
|
|||
* @param[in] ccr value to be written in the CCR register
|
||||
*/
|
||||
#define dmaSetupChannel(dmap, ch, cndtr, cmar, ccr) { \
|
||||
stm32_dma_channel_t *dmachp = &dmap->channels[ch]; \
|
||||
(dmachp)->CNDTR = (uint32_t)(cndtr); \
|
||||
(dmachp)->CMAR = (uint32_t)(cmar); \
|
||||
(dmachp)->CCR = (uint32_t)(ccr); \
|
||||
dmaChannelSetup(&(dmap)->channels[ch], (cndtr), (cmar), (ccr)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @brief DMA channel enable by channel ID.
|
||||
* @note Channels are numbered from 0 to 6, use the appropriate macro
|
||||
* as parameter.
|
||||
*
|
||||
|
@ -155,11 +198,11 @@ typedef struct {
|
|||
* @param[in] ch channel number
|
||||
*/
|
||||
#define dmaEnableChannel(dmap, ch) { \
|
||||
(dmap)->channels[ch].CCR |= 1; \
|
||||
dmaChannelEnable(&(dmap)->channels[ch]); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @brief DMA channel disable by channel ID.
|
||||
* @note Channels are numbered from 0 to 6, use the appropriate macro
|
||||
* as parameter.
|
||||
*
|
||||
|
@ -167,7 +210,7 @@ typedef struct {
|
|||
* @param[in] ch channel number
|
||||
*/
|
||||
#define dmaDisableChannel(dmap, ch) { \
|
||||
(dmap)->channels[ch].CCR = 0; \
|
||||
dmaChannelDisable(&(dmap)->channels[ch]); \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -80,7 +80,10 @@
|
|||
- NEW: Added a generic BaseFileStream interface for future File System
|
||||
implementations or integrations (untested and not sure if it will stay or
|
||||
change).
|
||||
- OPT: Speed optimizations of the STM32 SPI driver, improved latency.
|
||||
- CHANGE: Modified the STM32 ADC driver to use the new DMA infrastructure.
|
||||
- CHANGE: Modified the STM32 SPI driver to use the new DMA infrastructure.
|
||||
- CHANGE: Added DMA cleanup code to the STM32 dmaInit() function.
|
||||
- CHANGE: Simplified preprocessor conditions in the STM32 serial driver.
|
||||
- CHANGE: Renamed most of the STM32 HAL settings macro names in order to
|
||||
make names more consistent.
|
||||
|
|
Loading…
Reference in New Issue