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);
void twr_dma_channel_config(twr_dma_channel_t channel, twr_dma_channel_config_t *config)
Configure DMA channel.
void twr_dma_channel_run(twr_dma_channel_t channel)
Start 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.
twr_dma_event_t
DMA channel event.
void twr_dma_init(void)
Initialize DMA.
twr_dma_channel_t
DMA channels.
void twr_dma_channel_stop(twr_dma_channel_t channel)
Stop DMA channel.
@ TWR_DMA_EVENT_DONE
DMA channel event done.
@ TWR_DMA_SIZE_2
DMA channel data size 2B.
@ TWR_DMA_SIZE_4
DMA channel data size 4B.
@ TWR_DMA_DIRECTION_TO_PERIPHERAL
DMA channel direction from RAM to peripheral.
@ TWR_DMA_CHANNEL_7
DMA channel 7.
@ TWR_DMA_CHANNEL_6
DMA channel 6.
@ TWR_DMA_CHANNEL_1
DMA channel 1.
@ TWR_DMA_CHANNEL_5
DMA channel 5, used for SPI.
@ TWR_DMA_CHANNEL_2
DMA channel 2.
@ TWR_DMA_CHANNEL_3
DMA channel 3.
@ TWR_DMA_CHANNEL_4
DMA channel 4.
@ TWR_DMA_MODE_CIRCULAR
DMA channel mode circular.
@ TWR_DMA_MODE_STANDARD
DMA channel mode standard.
size_t twr_fifo_irq_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO from interrupt.
size_t twr_fifo_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO.
void twr_fifo_init(twr_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
#define TWR_TICK_INFINITY
Maximum timestamp value.
DMA channel configuration.
twr_dma_mode_t mode
DMA channel mode.
twr_dma_direction_t direction
DMA channel direction.
twr_dma_request_t request
DMA channel request.
void * address_peripheral
Peripheral address.
twr_dma_size_t data_size_memory
DMA channel memory data size.
size_t length
DMA channel data length.
void * address_memory
RAM memory address.
twr_dma_size_t data_size_peripheral
DMA channel peripheral data size.
twr_dma_priority_t priority
DMA channel priority.
Structure of FIFO instance.