stmhal: On SysTick IRQ, only process one DMA channel at a time.

This can be generalised if/when more processing is needed by SysTick.

Thanks to @chuckbook for the idea.
This commit is contained in:
Damien George 2015-11-24 15:40:59 +00:00
parent 9936aa3f87
commit 22bd23114a
3 changed files with 13 additions and 7 deletions

View File

@ -220,14 +220,16 @@ void dma_invalidate_channel(DMA_Stream_TypeDef *dma_stream, uint32_t dma_channel
} }
} }
// Called from the SysTick handler (once per millisecond) // Called from the SysTick handler
void dma_idle_handler() { // We use LSB of tick to select which controller to process
void dma_idle_handler(int tick) {
static const uint32_t controller_mask[] = { static const uint32_t controller_mask[] = {
DMA1_ENABLE_MASK, DMA2_ENABLE_MASK DMA1_ENABLE_MASK, DMA2_ENABLE_MASK
}; };
for (int controller = 0; controller < NCONTROLLERS; controller++) { {
int controller = tick & 1;
if (dma_idle.counter[controller] == 0) { if (dma_idle.counter[controller] == 0) {
continue; return;
} }
if (++dma_idle.counter[controller] > DMA_IDLE_TICK_MAX) { if (++dma_idle.counter[controller] > DMA_IDLE_TICK_MAX) {
if ((dma_enable_mask & controller_mask[controller]) == 0) { if ((dma_enable_mask & controller_mask[controller]) == 0) {

View File

@ -38,7 +38,7 @@ typedef union {
extern volatile dma_idle_count_t dma_idle; extern volatile dma_idle_count_t dma_idle;
#define DMA_IDLE_ENABLED() (dma_idle.enabled != 0) #define DMA_IDLE_ENABLED() (dma_idle.enabled != 0)
#define DMA_SYSTICK_MASK 0x0F #define DMA_SYSTICK_MASK 0x0e
#define DMA_MSECS_PER_SYSTICK (DMA_SYSTICK_MASK + 1) #define DMA_MSECS_PER_SYSTICK (DMA_SYSTICK_MASK + 1)
#define DMA_IDLE_TICK_MAX (8) // 128 msec #define DMA_IDLE_TICK_MAX (8) // 128 msec
#define DMA_IDLE_TICK(tick) (((tick) & DMA_SYSTICK_MASK) == 0) #define DMA_IDLE_TICK(tick) (((tick) & DMA_SYSTICK_MASK) == 0)
@ -48,4 +48,4 @@ extern const DMA_InitTypeDef dma_init_struct_spi_i2c;
void dma_init(DMA_HandleTypeDef *dma, DMA_Stream_TypeDef *dma_stream, const DMA_InitTypeDef *dma_init, uint32_t dma_channel, uint32_t direction, void *data); void dma_init(DMA_HandleTypeDef *dma, DMA_Stream_TypeDef *dma_stream, const DMA_InitTypeDef *dma_init, uint32_t dma_channel, uint32_t direction, void *data);
void dma_deinit(DMA_HandleTypeDef *dma); void dma_deinit(DMA_HandleTypeDef *dma);
void dma_invalidate_channel(DMA_Stream_TypeDef *dma_stream, uint32_t dma_channel); void dma_invalidate_channel(DMA_Stream_TypeDef *dma_stream, uint32_t dma_channel);
void dma_idle_handler(); void dma_idle_handler(int controller);

View File

@ -269,8 +269,12 @@ void SysTick_Handler(void) {
// work properly. // work properly.
SysTick->CTRL; SysTick->CTRL;
// Right now we just have the DMA controllers to process during this
// interrupt and we use a custom dispatch handler. If this needs to
// be generalised in the future then a dispatch table can be used as
// follows: ((void(*)(void))(systick_dispatch[uwTick & 0xf]))();
if (DMA_IDLE_ENABLED() && DMA_IDLE_TICK(uwTick)) { if (DMA_IDLE_ENABLED() && DMA_IDLE_TICK(uwTick)) {
dma_idle_handler(); dma_idle_handler(uwTick);
} }
} }