rework #4
43
drv/dma.c
43
drv/dma.c
@ -19,9 +19,9 @@
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static void configure_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph, volatile void* mem,
|
||||
uint16_t size);
|
||||
|
||||
enum DmaConfig config_mask, volatile void* periph);
|
||||
static void start_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size);
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
@ -36,8 +36,8 @@ static volatile void* dma2_cb_params[5];
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph, volatile void* mem,
|
||||
uint16_t size, DmaCallback callback, volatile void* cb_param)
|
||||
enum DmaConfig config_mask, volatile void* periph,
|
||||
DmaCallback callback, volatile void* cb_param)
|
||||
{
|
||||
//reset peripheral first, to ensure proper configuration
|
||||
dma_reset(dma, channel);
|
||||
@ -45,7 +45,7 @@ void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
rcc_enable(RCC_AHB_DMA1, RCC_APB1_NONE, RCC_APB2_NONE);
|
||||
configure_dma(dma1, channel, config_mask, periph, mem, size);
|
||||
configure_dma(dma1, channel, config_mask, periph);
|
||||
if (callback) {
|
||||
dma1_callbacks[channel] = callback;
|
||||
dma1_cb_params[channel] = cb_param;
|
||||
@ -54,7 +54,7 @@ void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
rcc_enable(RCC_AHB_DMA2, RCC_APB1_NONE, RCC_APB2_NONE);
|
||||
configure_dma(dma2, channel, config_mask, periph, mem, size);
|
||||
configure_dma(dma2, channel, config_mask, periph);
|
||||
if (callback) {
|
||||
dma2_callbacks[channel] = callback;
|
||||
dma2_cb_params[channel] = cb_param;
|
||||
@ -110,20 +110,21 @@ void dma_exit_critical(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
void dma_start(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
reg_set(dma1->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
if (dma1_callbacks[channel]) {
|
||||
nvic_enable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
start_dma(dma1, channel, mem, size);
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
reg_set(dma2->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
if (dma2_callbacks[channel]) {
|
||||
nvic_enable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
}
|
||||
start_dma(dma2, channel, mem, size);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -146,7 +147,7 @@ void dma_enter_critical(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
}
|
||||
}
|
||||
|
||||
void dma_disable(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
void dma_stop(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
@ -185,21 +186,27 @@ uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
static void configure_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph, volatile void* mem,
|
||||
uint16_t size)
|
||||
enum DmaConfig config_mask, volatile void* periph)
|
||||
{
|
||||
volatile struct DMA_CHANNEL* regs = &dma->CHANNELS[channel];
|
||||
|
||||
//registers should already be at reset value, apply new config
|
||||
regs->CCR.word = config_mask;
|
||||
reg_write(regs->CNDTR, DMA_CNDTR_NDT, size);
|
||||
regs->CPAR = (uint32_t)periph;
|
||||
regs->CMAR = (uint32_t)mem;
|
||||
|
||||
//only enable channel when everything is configured
|
||||
reg_set(regs->CCR, DMA_CCR_EN);
|
||||
}
|
||||
|
||||
static void start_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size)
|
||||
{
|
||||
volatile struct DMA_CHANNEL* regs = &dma->CHANNELS[channel];
|
||||
|
||||
//registers should already be configured, apply transfer config
|
||||
reg_write(regs->CNDTR, DMA_CNDTR_NDT, size);
|
||||
regs->CMAR = (uint32_t)mem;
|
||||
|
||||
//only start transfer when everything is configured
|
||||
reg_set(regs->CCR, DMA_CCR_EN);
|
||||
}
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -88,8 +88,8 @@ struct DmaParam {
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph, volatile void* mem,
|
||||
uint16_t size, DmaCallback callback, volatile void* cb_param);
|
||||
enum DmaConfig config_mask, volatile void* periph,
|
||||
DmaCallback callback, volatile void* cb_param);
|
||||
|
||||
void dma_configure_mem2mem(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfigM2M config_mask, const void* src, void* dest,
|
||||
@ -99,11 +99,12 @@ void dma_reset(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
void dma_exit_critical(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
void dma_enable(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
void dma_start(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size);
|
||||
|
||||
void dma_enter_critical(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
void dma_disable(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
void dma_stop(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channe);
|
||||
|
||||
|
||||
@ -192,12 +192,15 @@ const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph)
|
||||
switch (periph) {
|
||||
case USART_PERIPH_1:
|
||||
param = &usart1_tx_param;
|
||||
reg_set(usart1->CR3, USART_CR3_DMAT);
|
||||
break;
|
||||
case USART_PERIPH_2:
|
||||
param = &usart2_tx_param;
|
||||
reg_set(usart2->CR3, USART_CR3_DMAT);
|
||||
break;
|
||||
case USART_PERIPH_3:
|
||||
param = &usart3_tx_param;
|
||||
reg_set(usart3->CR3, USART_CR3_DMAT);
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
@ -31,17 +31,18 @@ void dma_cbuf_configure(volatile struct DmaCircBuffer* buffer,
|
||||
|
||||
buffer->buffer = raw_buffer;
|
||||
|
||||
buffer->param = param;
|
||||
buffer->priority = priority;
|
||||
|
||||
buffer->size = buffer_size;
|
||||
buffer->begin = 0;
|
||||
|
||||
buffer->dma = param->dma;
|
||||
buffer->channel = param->channel;
|
||||
|
||||
buffer->dma_looped = false;
|
||||
|
||||
dma_configure(buffer->param->dma, buffer->param->channel,
|
||||
buffer->param->config, buffer->param->periph,
|
||||
buffer->buffer, buffer->size, cbuf_callback, buffer);
|
||||
dma_configure(buffer->dma, buffer->channel,
|
||||
DMA_CONFIG | param->config | priority,
|
||||
param->periph, cbuf_callback, buffer);
|
||||
dma_start(buffer->dma, buffer->channel, buffer->buffer, buffer->size);
|
||||
}
|
||||
|
||||
uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer,
|
||||
@ -49,7 +50,7 @@ uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer,
|
||||
{
|
||||
//retreive the current end of the buffer based on the DMA's progress
|
||||
uint16_t end = buffer->size
|
||||
- dma_get_remaining(buffer->param->dma, buffer->param->channel);
|
||||
- dma_get_remaining(buffer->dma, buffer->channel);
|
||||
|
||||
//check for bytes to read and overflow
|
||||
if ((end > buffer->begin) && buffer->dma_looped) {
|
||||
@ -85,4 +86,3 @@ static void cbuf_callback(enum DmaIRQSource src, volatile void* param)
|
||||
buffer->dma_looped = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -23,12 +23,12 @@
|
||||
struct DmaCircBuffer {
|
||||
volatile void* buffer; //the buffer to use as a circular buffer
|
||||
|
||||
const struct DmaParam* param;
|
||||
enum DmaConfig priority; //DMA config, must correspond to peripheral
|
||||
|
||||
uint16_t size; //the size of the buffer
|
||||
uint16_t begin; //pointer to the current begin of the buffer
|
||||
|
||||
enum DmaPeriph dma;
|
||||
enum DmaChannel channel;
|
||||
|
||||
bool dma_looped; //whether the DMA looped or not (buffer overflow)
|
||||
};
|
||||
|
||||
|
||||
@ -31,15 +31,18 @@ void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer,
|
||||
|
||||
buffer->raw_buffer = raw_buffer;
|
||||
|
||||
buffer->param = param;
|
||||
buffer->priority = priority;
|
||||
|
||||
buffer->buffer_size = buffer_size / 2;
|
||||
|
||||
buffer->byte_index = 0;
|
||||
buffer->buffer_index = 0;
|
||||
buffer->dma = param->dma;
|
||||
buffer->channel = param->channel;
|
||||
|
||||
buffer->dma_running = false;
|
||||
|
||||
dma_configure(buffer->dma, buffer->channel,
|
||||
DMA_CONFIG | param->config | priority,
|
||||
param->periph, mbuf_callback, buffer);
|
||||
}
|
||||
|
||||
uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer,
|
||||
@ -66,12 +69,10 @@ void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer)
|
||||
}
|
||||
|
||||
//start a new transfer
|
||||
dma_configure(buffer->param->dma, buffer->param->channel,
|
||||
DMA_CONFIG | buffer->param->config | buffer->priority,
|
||||
buffer->param->periph,
|
||||
&buffer->raw_buffer[buffer->buffer_index * buffer->buffer_size],
|
||||
buffer->byte_index, mbuf_callback, buffer);
|
||||
buffer->dma_running = true;
|
||||
dma_start(buffer->dma, buffer->channel,
|
||||
&buffer->raw_buffer[buffer->buffer_index * buffer->buffer_size],
|
||||
buffer->byte_index);
|
||||
|
||||
buffer->byte_index = 0;
|
||||
++buffer->buffer_index;
|
||||
@ -93,7 +94,7 @@ static void mbuf_callback(enum DmaIRQSource src, volatile void* param)
|
||||
{
|
||||
(void)src; //only transfer complete expected
|
||||
volatile struct DmaMultiBuffer* buffer = param;
|
||||
|
||||
dma_stop(buffer->dma, buffer->channel);
|
||||
buffer->dma_running = false;
|
||||
}
|
||||
|
||||
|
||||
@ -23,13 +23,12 @@
|
||||
struct DmaMultiBuffer {
|
||||
uint8_t* raw_buffer;
|
||||
|
||||
const struct DmaParam* param;
|
||||
enum DmaConfig priority;
|
||||
|
||||
uint16_t buffer_size;
|
||||
|
||||
uint8_t byte_index;
|
||||
uint8_t buffer_index;
|
||||
enum DmaPeriph dma;
|
||||
enum DmaChannel channel;
|
||||
|
||||
bool dma_running;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user