3 #include <twr_scheduler.h> 7 #define _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(__CHANNEL) \ 8 if ((DMA1->ISR & DMA_ISR_GIF##__CHANNEL) != 0) \ 10 if ((DMA1->ISR & DMA_ISR_TEIF##__CHANNEL) != 0) \ 12 _twr_dma_irq_handler(TWR_DMA_CHANNEL_##__CHANNEL, TWR_DMA_EVENT_ERROR); \ 14 else if ((DMA1->ISR & DMA_ISR_HTIF##__CHANNEL) != 0) \ 16 _twr_dma_irq_handler(TWR_DMA_CHANNEL_##__CHANNEL, TWR_DMA_EVENT_HALF_DONE); \ 17 DMA1->IFCR |= DMA_IFCR_CHTIF##__CHANNEL; \ 19 else if ((DMA1->ISR & DMA_ISR_TCIF##__CHANNEL) != 0) \ 21 _twr_dma_irq_handler(TWR_DMA_CHANNEL_##__CHANNEL, TWR_DMA_EVENT_DONE); \ 22 DMA1->IFCR |= DMA_IFCR_CTCIF##__CHANNEL; \ 41 DMA_Channel_TypeDef *instance;
52 static void _twr_dma_task(
void *param);
58 if (_twr_dma.is_initialized)
72 twr_fifo_init(&_twr_dma.fifo_pending, _twr_dma_pending_event_buffer,
sizeof(_twr_dma_pending_event_buffer));
77 RCC->AHBENR |= RCC_AHBENR_DMA1EN;
83 NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
84 NVIC_EnableIRQ(DMA1_Channel1_IRQn);
87 NVIC_SetPriority(DMA1_Channel2_3_IRQn, 1);
88 NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
91 NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 2);
92 NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
97 DMA_Channel_TypeDef *dma_channel = _twr_dma.channel[channel].instance;
99 uint32_t dma_cselr_pos = channel * 4;
106 dma_channel->CCR |= DMA_CCR_DIR;
110 dma_channel->CCR &= ~DMA_CCR_DIR;
114 dma_channel->CCR &= ~DMA_CCR_MSIZE_Msk;
118 dma_channel->CCR |= DMA_CCR_MSIZE_0;
122 dma_channel->CCR |= DMA_CCR_MSIZE_1;
126 dma_channel->CCR &= ~DMA_CCR_PSIZE_Msk;
130 dma_channel->CCR |= DMA_CCR_PSIZE_0;
134 dma_channel->CCR |= DMA_CCR_PSIZE_1;
140 dma_channel->CCR &= ~DMA_CCR_CIRC;
144 dma_channel->CCR |= DMA_CCR_CIRC;
148 dma_channel->CCR |= DMA_CCR_MINC;
151 dma_channel->CCR &= ~DMA_CCR_PL_Msk;
152 dma_channel->CCR |= config->
priority << DMA_CCR_PL_Pos;
155 DMA1_CSELR->CSELR &= ~(0xf << dma_cselr_pos);
156 DMA1_CSELR->CSELR |= config->
request << dma_cselr_pos;
159 dma_channel->CNDTR = config->
length;
168 dma_channel->CCR |= DMA_CCR_TCIE | DMA_CCR_HTIE | DMA_CCR_TEIE;
175 _twr_dma.channel[channel].event_handler = event_handler;
176 _twr_dma.channel[channel].event_param = event_param;
181 _twr_dma.channel[channel].instance->CCR |= DMA_CCR_EN;
186 _twr_dma.channel[channel].instance->CCR &= ~DMA_CCR_EN;
191 return (
size_t) _twr_dma.channel[channel].instance->CNDTR;
194 void _twr_dma_task(
void *param)
202 if (_twr_dma.channel[pending_event.channel].event_handler != NULL)
204 _twr_dma.channel[pending_event.channel].event_handler(pending_event.channel, pending_event.event, _twr_dma.channel[pending_event.channel].event_param);
211 if (event ==
TWR_DMA_EVENT_DONE && !(_twr_dma.channel[channel].instance->CCR & DMA_CCR_CIRC))
223 void DMA1_Channel1_IRQHandler(
void)
225 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(1);
228 void DMA1_Channel2_3_IRQHandler(
void)
230 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(2);
232 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(3);
235 void DMA1_Channel4_5_6_7_IRQHandler(
void)
237 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(4);
239 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(5);
241 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(6);
243 _TWR_DMA_CHECK_IRQ_OF_CHANNEL_(7);
twr_dma_request_t request
DMA channel request.
twr_dma_channel_t
DMA channels.
DMA channel data size 4B.
size_t twr_fifo_irq_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO from interrupt.
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
void * address_memory
RAM memory address.
size_t length
DMA channel data length.
twr_dma_mode_t mode
DMA channel mode.
DMA channel direction from RAM to peripheral.
void twr_dma_channel_config(twr_dma_channel_t channel, twr_dma_channel_config_t *config)
Configure DMA channel.
void twr_dma_set_event_handler(twr_dma_channel_t channel, void(*event_handler)(twr_dma_channel_t, twr_dma_event_t, void *), void *event_param)
Set callback function.
void * address_peripheral
Peripheral address.
void twr_fifo_init(twr_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
DMA channel data size 2B.
void twr_dma_channel_run(twr_dma_channel_t channel)
Start DMA channel.
DMA channel configuration.
twr_dma_event_t
DMA channel event.
twr_dma_direction_t direction
DMA channel direction.
DMA channel mode standard.
DMA channel 5, used for SPI.
twr_dma_size_t data_size_memory
DMA channel memory data size.
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
void twr_dma_channel_stop(twr_dma_channel_t channel)
Stop DMA channel.
size_t twr_fifo_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO.
DMA channel mode circular.
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Structure of FIFO instance.
void twr_dma_init(void)
Initialize DMA.
twr_dma_size_t data_size_peripheral
DMA channel peripheral data size.
#define TWR_TICK_INFINITY
Maximum timestamp value.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_dma_priority_t priority
DMA channel priority.