Added DMA sharing in the STM32 HAL.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2874 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2011-04-10 16:45:41 +00:00
parent 8bfbb8d4d9
commit 618a978da8
23 changed files with 577 additions and 498 deletions

View File

@ -51,7 +51,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -128,9 +128,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -144,9 +142,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -59,7 +59,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -136,9 +136,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -152,9 +150,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -48,40 +48,36 @@ ADCDriver ADCD1;
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Shared ADC DMA ISR service routine.
*
* @param[in] adcp pointer to the @p ADCDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_ADC_DMA_ERROR_HOOK)
if ((flags & DMA_ISR_TEIF1) != 0) {
STM32_ADC_DMA_ERROR_HOOK(spip);
}
#else
(void)flags;
#endif
if ((flags & DMA_ISR_HTIF1) != 0) {
/* Half transfer processing.*/
_adc_isr_half_code(adcp);
}
if ((flags & DMA_ISR_TCIF1) != 0) {
/* Transfer complete processing.*/
_adc_isr_full_code(adcp);
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
/**
* @brief ADC1 DMA interrupt handler (channel 1).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR;
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_1);
if ((isr & DMA_ISR_TEIF1) != 0) {
/* DMA error processing.*/
STM32_ADC1_DMA_ERROR_HOOK();
}
if ((isr & DMA_ISR_HTIF1) != 0) {
/* Half transfer processing.*/
_adc_isr_half_code(&ADCD1);
}
if ((isr & DMA_ISR_TCIF1) != 0) {
/* Transfer complete processing.*/
_adc_isr_full_code(&ADCD1);
}
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -136,7 +132,8 @@ void adc_lld_start(ADCDriver *adcp) {
if (adcp->state == ADC_STOP) {
#if STM32_ADC_USE_ADC1
if (&ADCD1 == adcp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_1,
(stm32_dmaisr_t)adc_lld_serve_rx_interrupt, (void *)adcp);
NVICEnableVector(DMA1_Channel1_IRQn,
CORTEX_PRIORITY_MASK(STM32_ADC_ADC1_IRQ_PRIORITY));
dmaChannelSetPeripheral(adcp->dmachp, &ADC1->DR);
@ -167,7 +164,7 @@ void adc_lld_stop(ADCDriver *adcp) {
ADC1->CR1 = 0;
ADC1->CR2 = 0;
NVICDisableVector(DMA1_Channel1_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_1);
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
}
#endif

View File

@ -94,12 +94,12 @@
#endif
/**
* @brief ADC1 DMA error hook.
* @brief ADC DMA error hook.
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
#if !defined(STM32_ADC_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
#endif
/*===========================================================================*/
@ -114,6 +114,10 @@
#error "ADC driver activated but no ADC peripheral assigned"
#endif
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/

View File

@ -71,7 +71,7 @@ void hal_lld_init(void) {
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
#if HAL_USE_ADC || HAL_USE_SPI || HAL_USE_UART
#if defined(STM32_DMA_REQUIRED)
dmaInit();
#endif
}

View File

@ -82,11 +82,21 @@ static uint16_t dummyrx;
}
/**
* @brief Shared end-of-transfer service routine.
* @brief Shared 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 serve_interrupt(SPIDriver *spip) {
static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_SPI_DMA_ERROR_HOOK)
if ((flags & DMA_ISR_TEIF1) != 0) {
STM32_SPI_DMA_ERROR_HOOK(spip);
}
#else
(void)flags;
#endif
/* Stop everything.*/
dma_stop(spip);
@ -96,115 +106,29 @@ static void serve_interrupt(SPIDriver *spip) {
_spi_isr_code(spip);
}
/**
* @brief Shared 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) {
/* DMA errors handling.*/
#if defined(STM32_SPI_DMA_ERROR_HOOK)
if ((flags & DMA_ISR_TEIF1) != 0) {
STM32_SPI_DMA_ERROR_HOOK(spip);
}
#else
(void)spip;
(void)flags;
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
/**
* @brief SPI1 RX DMA interrupt handler (channel 2).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF2) != 0) {
STM32_SPI_SPI1_DMA_ERROR_HOOK();
}
serve_interrupt(&SPID1);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
CH_IRQ_EPILOGUE();
}
/**
* @brief SPI1 TX DMA interrupt handler (channel 3).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
CH_IRQ_PROLOGUE();
STM32_SPI_SPI1_DMA_ERROR_HOOK();
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
CH_IRQ_EPILOGUE();
}
#endif
#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
/**
* @brief SPI2 RX DMA interrupt handler (channel 4).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) {
STM32_SPI_SPI2_DMA_ERROR_HOOK();
}
serve_interrupt(&SPID2);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
CH_IRQ_EPILOGUE();
}
/**
* @brief SPI2 TX DMA interrupt handler (channel 5).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
CH_IRQ_PROLOGUE();
STM32_SPI_SPI2_DMA_ERROR_HOOK();
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
CH_IRQ_EPILOGUE();
}
#endif
#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
/**
* @brief SPI3 RX DMA interrupt handler (DMA2, channel 1).
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch1_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA2->ISR & DMA_ISR_TEIF1) != 0) {
STM32_SPI_SPI3_DMA_ERROR_HOOK();
}
serve_interrupt(&SPID3);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_1);
CH_IRQ_EPILOGUE();
}
/**
* @brief SPI3 TX DMA2 interrupt handler (DMA2, channel 2).
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) {
CH_IRQ_PROLOGUE();
STM32_SPI_SPI3_DMA_ERROR_HOOK();
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_2);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -256,7 +180,11 @@ void spi_lld_start(SPIDriver *spip) {
if (spip->state == SPI_STOP) {
#if STM32_SPI_USE_SPI1
if (&SPID1 == spip) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_2,
(stm32_dmaisr_t)spi_lld_serve_rx_interrupt, (void *)spip);
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_3,
(stm32_dmaisr_t)spi_lld_serve_tx_interrupt, (void *)spip);
NVICEnableVector(DMA1_Channel2_IRQn,
CORTEX_PRIORITY_MASK(STM32_SPI_SPI1_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel3_IRQn,
@ -266,7 +194,11 @@ void spi_lld_start(SPIDriver *spip) {
#endif
#if STM32_SPI_USE_SPI2
if (&SPID2 == spip) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_4,
(stm32_dmaisr_t)spi_lld_serve_rx_interrupt, (void *)spip);
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_5,
(stm32_dmaisr_t)spi_lld_serve_tx_interrupt, (void *)spip);
NVICEnableVector(DMA1_Channel4_IRQn,
CORTEX_PRIORITY_MASK(STM32_SPI_SPI2_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel5_IRQn,
@ -276,7 +208,11 @@ void spi_lld_start(SPIDriver *spip) {
#endif
#if STM32_SPI_USE_SPI3
if (&SPID3 == spip) {
dmaEnable(DMA2_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA2_ID, STM32_DMA_CHANNEL_1,
(stm32_dmaisr_t)spi_lld_serve_rx_interrupt, (void *)spip);
dmaAllocate(STM32_DMA2_ID, STM32_DMA_CHANNEL_2,
(stm32_dmaisr_t)spi_lld_serve_tx_interrupt, (void *)spip);
NVICEnableVector(DMA2_Channel1_IRQn,
CORTEX_PRIORITY_MASK(STM32_SPI_SPI3_IRQ_PRIORITY));
NVICEnableVector(DMA2_Channel2_IRQn,
@ -324,7 +260,8 @@ void spi_lld_stop(SPIDriver *spip) {
if (&SPID1 == spip) {
NVICDisableVector(DMA1_Channel2_IRQn);
NVICDisableVector(DMA1_Channel3_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_2);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_3);
RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN;
}
#endif
@ -332,7 +269,8 @@ void spi_lld_stop(SPIDriver *spip) {
if (&SPID2 == spip) {
NVICDisableVector(DMA1_Channel4_IRQn);
NVICDisableVector(DMA1_Channel5_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_4);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_5);
RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN;
}
#endif
@ -340,7 +278,8 @@ void spi_lld_stop(SPIDriver *spip) {
if (&SPID3 == spip) {
NVICDisableVector(DMA2_Channel1_IRQn);
NVICDisableVector(DMA2_Channel2_IRQn);
dmaDisable(DMA2_ID);
dmaRelease(STM32_DMA2_ID, STM32_DMA_CHANNEL_1);
dmaRelease(STM32_DMA2_ID, STM32_DMA_CHANNEL_2);
RCC->APB1ENR &= ~RCC_APB1ENR_SPI3EN;
}
#endif

View File

@ -118,30 +118,12 @@
#endif
/**
* @brief SPI1 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
* @brief SPI DMA error hook.
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_SPI_SPI1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#endif
/**
* @brief SPI2 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
*/
#if !defined(STM32_SPI_SPI2_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#endif
/**
* @brief SPI3 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
*/
#if !defined(STM32_SPI_SPI3_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
#endif
/*===========================================================================*/
@ -164,6 +146,10 @@
#error "SPI driver activated but no SPI peripheral assigned"
#endif
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/

View File

@ -23,23 +23,43 @@
* @brief STM32 DMA helper driver code.
*
* @addtogroup STM32_DMA
* @details DMA sharing helper driver. In the STM32 the DMA channels are a
* shared resource, this driver allows to allocate and free DMA
* channels at runtime in order to allow all the other device
* drivers to coordinate the access to the resource.
* @note The DMA ISR handlers are all declared into this module because
* sharing, the various device drivers can associate a callback to
* IRSs when allocating channels.
* @{
*/
#include "ch.h"
#include "hal.h"
#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables. */
/* Driver local variables and types. */
/*===========================================================================*/
static cnt_t dmacnt1;
/**
* @brief DMA ISR redirector type.
*/
typedef struct {
stm32_dmaisr_t dmaisrfunc;
void *dmaisrparam;
} dma_isr_redir_t;
static uint32_t dmamsk1;
static dma_isr_redir_t dma1[7];
#if STM32_HAS_DMA2
static cnt_t dmacnt2;
static uint32_t dmamsk2;
static dma_isr_redir_t dma2[5];
#endif
/*===========================================================================*/
@ -50,6 +70,224 @@ static cnt_t dmacnt2;
/* Driver interrupt handlers. */
/*===========================================================================*/
/**
* @brief DMA1 channel 1 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_1 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_1);
if (dma1[0].dmaisrfunc)
dma1[0].dmaisrfunc(dma1[0].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 2 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_2 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
if (dma1[1].dmaisrfunc)
dma1[1].dmaisrfunc(dma1[1].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 3 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_3 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
if (dma1[2].dmaisrfunc)
dma1[2].dmaisrfunc(dma1[2].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 4 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_4 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
if (dma1[3].dmaisrfunc)
dma1[3].dmaisrfunc(dma1[3].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 5 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_5 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
if (dma1[4].dmaisrfunc)
dma1[4].dmaisrfunc(dma1[4].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 6 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_6 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
if (dma1[5].dmaisrfunc)
dma1[5].dmaisrfunc(dma1[5].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA1 channel 7 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch7_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA1->ISR >> (STM32_DMA_CHANNEL_7 * 4);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_7);
if (dma1[6].dmaisrfunc)
dma1[6].dmaisrfunc(dma1[6].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
#if STM32_HAS_DMA2 || defined(__DOXYGEN__)
/**
* @brief DMA2 channel 1 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch1_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA2->ISR >> (STM32_DMA_CHANNEL_1 * 4);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_1);
if (dma2[0].dmaisrfunc)
dma2[0].dmaisrfunc(dma2[0].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA2 channel 2 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA2->ISR >> (STM32_DMA_CHANNEL_2 * 4);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_2);
if (dma2[1].dmaisrfunc)
dma2[1].dmaisrfunc(dma2[1].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA2 channel 3 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch3_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA2->ISR >> (STM32_DMA_CHANNEL_3 * 4);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_3);
if (dma2[2].dmaisrfunc)
dma2[2].dmaisrfunc(dma2[2].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA2 channel 4 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch4_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA2->ISR >> (STM32_DMA_CHANNEL_4 * 4);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_4);
if (dma2[3].dmaisrfunc)
dma2[3].dmaisrfunc(dma2[3].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
/**
* @brief DMA2 channel 5 shared interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(DMA2_Ch5_IRQHandler) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = STM32_DMA2->ISR >> (STM32_DMA_CHANNEL_5 * 4);
dmaClearChannel(STM32_DMA2, STM32_DMA_CHANNEL_5);
if (dma2[4].dmaisrfunc)
dma2[4].dmaisrfunc(dma2[4].dmaisrparam, isr);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_HAS_DMA2 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -62,66 +300,135 @@ static cnt_t dmacnt2;
void dmaInit(void) {
int i;
dmacnt1 = 0;
for (i = STM32_DMA_CHANNEL_7; i >= STM32_DMA_CHANNEL_1; i--)
dmamsk1 = 0;
for (i = STM32_DMA_CHANNEL_7; i >= STM32_DMA_CHANNEL_1; i--) {
dmaDisableChannel(STM32_DMA1, i);
dma1[i].dmaisrfunc = NULL;
}
STM32_DMA1->IFCR = 0xFFFFFFFF;
#if STM32_HAS_DMA2
dmacnt2 = 0;
for (i = STM32_DMA_CHANNEL_5; i >= STM32_DMA_CHANNEL_1; i--)
dmamsk2 = 0;
for (i = STM32_DMA_CHANNEL_5; i >= STM32_DMA_CHANNEL_1; i--) {
dmaDisableChannel(STM32_DMA2, i);
dma2[i].dmaisrfunc = NULL;
}
STM32_DMA1->IFCR = 0xFFFFFFFF;
#endif
}
/**
* @brief Enables the specified DMA controller clock.
* @brief Allocates a DMA channel.
* @details The channel is allocated and, if required, the DMA clock enabled.
* Trying to allocate a channel already allocated is an illegal
* operation and is trapped if assertions are enabled.
* @pre The channel must not be already in use.
* @post The channel is allocated and the default ISR handler redirected
* to the specified function.
* @post The channel must be freed using @p dmaRelease() before it can
* be reused with another peripheral.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dma the DMA controller id
* @param[in] dma DMA controller id
* @param[in] channel requested channel id
* @param[in] func handling function pointer, can be @p NULL
* @param[in] param a parameter to be passed to the handling function
* @return The operation status.
* @retval FALSE operation successfully allocated.
* @retval TRUE the channel was already in use.
*
* @api
* @special
*/
void dmaEnable(uint32_t dma) {
void dmaAllocate(uint32_t dma, uint32_t channel,
stm32_dmaisr_t func, void *param) {
chDbgCheck(func != NULL, "dmaAllocate");
#if STM32_HAS_DMA2
switch (dma) {
case DMA1_ID:
if (dmacnt1++ == 0) {
case STM32_DMA1_ID:
#else
(void)dma;
#endif
/* Check if the channel is already taken.*/
chDbgAssert((dmamsk1 & (1 << channel)) == 0,
"dmaAllocate(), #1", "already allocated");
/* If the DMA unit was idle then the clock is enabled.*/
if (dmamsk1 == 0) {
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1->IFCR = 0x0FFFFFFF;
}
break;
dmamsk1 |= 1 << channel;
dma1[channel].dmaisrfunc = func;
dma1[channel].dmaisrparam = param;
#if STM32_HAS_DMA2
case DMA2_ID:
if (dmacnt2++ == 0) {
break;
case STM32_DMA2_ID:
/* Check if the channel is already taken.*/
chDbgAssert((dmamsk2 & (1 << channel)) == 0,
"dmaAllocate(), #2", "already allocated");
/* If the DMA unit was idle then the clock is enabled.*/
if (dmamsk1 == 0) {
RCC->AHBENR |= RCC_AHBENR_DMA2EN;
DMA2->IFCR = 0x0FFFFFFF;
}
dmamsk2 |= 1 << channel;
dma2[channel].dmaisrfunc = func;
dma2[channel].dmaisrparam = param;
break;
#endif
}
#endif
}
/**
* @brief Disables the specified DMA controller clock.
* @brief Releases a DMA channel.
* @details The channel is freed and, if required, the DMA clock disabled.
* Trying to release a unallocated channel is an illegal operation
* and is trapped if assertions are enabled.
* @pre The channel must have been allocated using @p dmaRequest().
* @post The channel is again available.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dma the DMA controller id
* @param[in] dma DMA controller id
* @param[in] channel requested channel id
*
* @api
* @special
*/
void dmaDisable(uint32_t dma) {
void dmaRelease(uint32_t dma, uint32_t channel) {
switch (dma) {
case DMA1_ID:
if (--dmacnt1 == 0)
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
break;
#if STM32_HAS_DMA2
case DMA2_ID:
if (--dmacnt2 == 0)
switch (dma) {
case STM32_DMA1_ID:
#else
(void)dma;
#endif
/* Check if the channel is not taken.*/
chDbgAssert((dmamsk1 & (1 << channel)) != 0,
"dmaRelease(), #1", "not allocated");
dma1[channel].dmaisrfunc = NULL;
dmamsk1 &= ~(1 << channel);
if (dmamsk1 == 0)
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
#if STM32_HAS_DMA2
break;
case STM32_DMA2_ID:
/* Check if the channel is not taken.*/
chDbgAssert((dmamsk2 & (1 << channel)) != 0,
"dmaRelease(), #2", "not allocated");
dma2[channel].dmaisrfunc = NULL;
dmamsk2 &= ~(1 << channel);
if (dmamsk2 == 0)
RCC->AHBENR &= ~RCC_AHBENR_DMA2EN;
break;
}
#endif
}
}
#endif /* STM32_DMA_REQUIRED */
/** @} */

View File

@ -36,11 +36,11 @@
/*===========================================================================*/
/** @brief DMA1 identifier.*/
#define DMA1_ID 0
#define STM32_DMA1_ID 0
/** @brief DMA2 identifier.*/
#if STM32_HAS_DMA2 || defined(__DOXYGEN__)
#define DMA2_ID 1
#define STM32_DMA2_ID 1
#endif
/*===========================================================================*/
@ -56,7 +56,7 @@
/*===========================================================================*/
/**
* @brief STM32 DMA channel memory structure.
* @brief STM32 DMA channel memory structure type.
*/
typedef struct {
volatile uint32_t CCR;
@ -67,7 +67,7 @@ typedef struct {
} stm32_dma_channel_t;
/**
* @brief STM32 DMA subsystem memory structure.
* @brief STM32 DMA subsystem memory structure type.
* @note This structure has been redefined here because it is convenient to
* have the channels organized as an array, the ST header does not
* do that.
@ -78,6 +78,14 @@ typedef struct {
stm32_dma_channel_t channels[7];
} stm32_dma_t;
/**
* @brief STM32 DMA ISR function type.
*
* @param[in] p parameter for the registered function
* @param[in] flags pre-shifted content of the ISR register
*/
typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
@ -128,11 +136,12 @@ typedef struct {
/**
* @brief Associates a peripheral data register to a DMA channel.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
* @param[in] cpar value to be written in the CPAR register
*
* @api
* @special
*/
#define dmaChannelSetPeripheral(dmachp, cpar) { \
(dmachp)->CPAR = (uint32_t)(cpar); \
@ -143,13 +152,14 @@ typedef struct {
* @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.
* @note This function can be invoked in both ISR or thread context.
*
* @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
*
* @api
* @special
*/
#define dmaChannelSetup(dmachp, cndtr, cmar, ccr) { \
(dmachp)->CNDTR = (uint32_t)(cndtr); \
@ -159,10 +169,11 @@ typedef struct {
/**
* @brief DMA channel enable by channel pointer.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
*
* @api
* @special
*/
#define dmaChannelEnable(dmachp) { \
(dmachp)->CCR |= DMA_CCR1_EN; \
@ -171,10 +182,11 @@ typedef struct {
/**
* @brief DMA channel disable by channel pointer.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmachp dmachp to a stm32_dma_channel_t structure
*
* @api
* @special
*/
#define dmaChannelDisable(dmachp) { \
(dmachp)->CCR = 0; \
@ -187,6 +199,7 @@ typedef struct {
* data register.
* @note Channels are numbered from 0 to 6, use the appropriate macro
* as parameter.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmap pointer to a stm32_dma_t structure
* @param[in] ch channel number
@ -194,7 +207,7 @@ typedef struct {
* @param[in] cmar value to be written in the CMAR register
* @param[in] ccr value to be written in the CCR register
*
* @api
* @special
*/
#define dmaSetupChannel(dmap, ch, cndtr, cmar, ccr) { \
dmaChannelSetup(&(dmap)->channels[ch], (cndtr), (cmar), (ccr)); \
@ -204,11 +217,12 @@ typedef struct {
* @brief DMA channel enable by channel ID.
* @note Channels are numbered from 0 to 6, use the appropriate macro
* as parameter.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmap pointer to a stm32_dma_t structure
* @param[in] ch channel number
*
* @api
* @special
*/
#define dmaEnableChannel(dmap, ch) { \
dmaChannelEnable(&(dmap)->channels[ch]); \
@ -218,11 +232,12 @@ typedef struct {
* @brief DMA channel disable by channel ID.
* @note Channels are numbered from 0 to 6, use the appropriate macro
* as parameter.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmap pointer to a stm32_dma_t structure
* @param[in] ch channel number
*
* @api
* @special
*/
#define dmaDisableChannel(dmap, ch) { \
dmaChannelDisable(&(dmap)->channels[ch]); \
@ -234,11 +249,12 @@ typedef struct {
* withdraw all the pending interrupt bits from the ISR register.
* @note Channels are numbered from 0 to 6, use the appropriate macro
* as parameter.
* @note This function can be invoked in both ISR or thread context.
*
* @param[in] dmap pointer to a stm32_dma_t structure
* @param[in] ch channel number
*
* @api
* @special
*/
#define dmaClearChannel(dmap, ch){ \
(dmap)->IFCR = 1 << ((ch) * 4); \
@ -252,8 +268,9 @@ typedef struct {
extern "C" {
#endif
void dmaInit(void);
void dmaEnable(uint32_t dma);
void dmaDisable(uint32_t dma);
void dmaAllocate(uint32_t dma, uint32_t channel,
stm32_dmaisr_t func, void *param);
void dmaRelease(uint32_t dma, uint32_t channel);
#ifdef __cplusplus
}
#endif

View File

@ -164,9 +164,29 @@ static void usart_start(UARTDriver *uartp) {
* @brief RX DMA common service routine.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
static void serve_rx_end_irq(UARTDriver *uartp) {
static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_UART_DMA_ERROR_HOOK)
if ((flags & DMA_ISR_TEIF1) != 0) {
STM32_UART_DMA_ERROR_HOOK(uartp);
}
#else
(void)flags;
#endif
if (uartp->rxstate == UART_RX_IDLE) {
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(uartp->dmap, uartp->dmarx);
uartp->rxstate = UART_RX_COMPLETE;
if (uartp->config->rxend_cb != NULL)
uartp->config->rxend_cb(uartp);
@ -177,14 +197,26 @@ static void serve_rx_end_irq(UARTDriver *uartp) {
set_rx_idle_loop(uartp);
}
}
}
/**
* @brief TX DMA common service routine.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
static void serve_tx_end_irq(UARTDriver *uartp) {
static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
/* DMA errors handling.*/
#if defined(STM32_UART_DMA_ERROR_HOOK)
if ((flags & DMA_ISR_TEIF1) != 0) {
STM32_UART_DMA_ERROR_HOOK(uartp);
}
#else
(void)flags;
#endif
dmaDisableChannel(uartp->dmap, uartp->dmatx);
/* A callback is generated, if enabled, after a completed transfer.*/
uartp->txstate = UART_TX_COMPLETE;
if (uartp->config->txend1_cb != NULL)
@ -194,6 +226,7 @@ static void serve_tx_end_irq(UARTDriver *uartp) {
if (uartp->txstate == UART_TX_COMPLETE)
uartp->txstate = UART_TX_IDLE;
}
/**
* @brief USART common service routine.
*
@ -224,58 +257,6 @@ static void serve_usart_irq(UARTDriver *uartp) {
/*===========================================================================*/
#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
/**
* @brief USART1 RX DMA interrupt handler (channel 5).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE();
uartp = &UARTD1;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF5) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
if (uartp->rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
serve_rx_end_irq(uartp);
}
CH_IRQ_EPILOGUE();
}
/**
* @brief USART1 TX DMA interrupt handler (channel 4).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
serve_tx_end_irq(&UARTD1);
CH_IRQ_EPILOGUE();
}
/**
* @brief USART1 IRQ handler.
*
@ -292,58 +273,6 @@ CH_IRQ_HANDLER(USART1_IRQHandler) {
#endif /* STM32_UART_USE_USART1 */
#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
/**
* @brief USART2 RX DMA interrupt handler (channel 6).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE();
uartp = &UARTD2;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF6) != 0) {
STM32_UART_USART2_DMA_ERROR_HOOK();
}
if (uartp->rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
serve_rx_end_irq(uartp);
}
CH_IRQ_EPILOGUE();
}
/**
* @brief USART2 TX DMA interrupt handler (channel 7).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch7_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF7) != 0) {
STM32_UART_USART2_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_7);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_7);
serve_tx_end_irq(&UARTD2);
CH_IRQ_EPILOGUE();
}
/**
* @brief USART2 IRQ handler.
*
@ -360,58 +289,6 @@ CH_IRQ_HANDLER(USART2_IRQHandler) {
#endif /* STM32_UART_USE_USART2 */
#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
/**
* @brief USART3 RX DMA interrupt handler (channel 3).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE();
uartp = &UARTD3;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF3) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
if (uartp->rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
if (uartp->config->rxchar_cb != NULL)
uartp->config->rxchar_cb(uartp, uartp->rxbuf);
}
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
serve_rx_end_irq(uartp);
}
CH_IRQ_EPILOGUE();
}
/**
* @brief USART3 TX DMA interrupt handler (channel 2).
*
* @isr
*/
CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF2) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
serve_tx_end_irq(&UARTD3);
CH_IRQ_EPILOGUE();
}
/**
* @brief USART3 IRQ handler.
*
@ -478,7 +355,11 @@ void uart_lld_start(UARTDriver *uartp) {
if (uartp->state == UART_STOP) {
#if STM32_UART_USE_USART1
if (&UARTD1 == uartp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_4,
(stm32_dmaisr_t)uart_lld_serve_tx_end_irq, (void *)uartp);
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_5,
(stm32_dmaisr_t)uart_lld_serve_rx_end_irq, (void *)uartp);
NVICEnableVector(USART1_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART1_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel4_IRQn,
@ -491,7 +372,11 @@ void uart_lld_start(UARTDriver *uartp) {
#if STM32_UART_USE_USART2
if (&UARTD2 == uartp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_6,
(stm32_dmaisr_t)uart_lld_serve_rx_end_irq, (void *)uartp);
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_7,
(stm32_dmaisr_t)uart_lld_serve_tx_end_irq, (void *)uartp);
NVICEnableVector(USART2_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART2_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel6_IRQn,
@ -504,7 +389,11 @@ void uart_lld_start(UARTDriver *uartp) {
#if STM32_UART_USE_USART3
if (&UARTD3 == uartp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
/* Note, the DMA must be enabled before the IRQs.*/
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_2,
(stm32_dmaisr_t)uart_lld_serve_tx_end_irq, (void *)uartp);
dmaAllocate(STM32_DMA1_ID, STM32_DMA_CHANNEL_3,
(stm32_dmaisr_t)uart_lld_serve_rx_end_irq, (void *)uartp);
NVICEnableVector(USART3_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART3_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel2_IRQn,
@ -549,7 +438,8 @@ void uart_lld_stop(UARTDriver *uartp) {
NVICDisableVector(USART1_IRQn);
NVICDisableVector(DMA1_Channel4_IRQn);
NVICDisableVector(DMA1_Channel5_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_4);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_5);
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
return;
}
@ -560,7 +450,8 @@ void uart_lld_stop(UARTDriver *uartp) {
NVICDisableVector(USART2_IRQn);
NVICDisableVector(DMA1_Channel6_IRQn);
NVICDisableVector(DMA1_Channel7_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_6);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_7);
RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
return;
}
@ -571,7 +462,8 @@ void uart_lld_stop(UARTDriver *uartp) {
NVICDisableVector(USART3_IRQn);
NVICDisableVector(DMA1_Channel2_IRQn);
NVICDisableVector(DMA1_Channel3_IRQn);
dmaDisable(DMA1_ID);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_2);
dmaRelease(STM32_DMA1_ID, STM32_DMA_CHANNEL_3);
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN;
return;
}

View File

@ -121,26 +121,8 @@
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_UART_USART1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#endif
/**
* @brief USART2 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_UART_USART2_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#endif
/**
* @brief USART3 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_UART_USART3_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
#endif
/*===========================================================================*/
@ -164,6 +146,10 @@
#error "UART driver activated but no USART/UART peripheral assigned"
#endif
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/

View File

@ -73,6 +73,9 @@
*** 2.3.2 ***
- FIX: Fixed spurious characters generated by Serial over USB driver (bug
3276379).
- NEW: Now it is possible to share DMA channels in the STM32 HAL thanks
to a centralized manager. Channels are allocated when the driver is
started and released when it is stopped.
- OPT: STM32 PWM driver implementation simplified.
- CHANGE: Now pwmChangePeriod() does not implicitly disable the active
PWM channels.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.

View File

@ -52,7 +52,7 @@
#define STM32_ADC_USE_ADC1 TRUE
#define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
/*
* CAN driver system settings.
@ -129,9 +129,7 @@
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
/*
* UART driver system settings.
@ -145,9 +143,7 @@
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt()
#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt()
/*
* USB driver system settings.