From f89fe12298046dd95f46da32c7bbd2fd340ea282 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Tue, 11 Jul 2023 11:44:54 +0200 Subject: [PATCH] Add circular rx buffer management --- drivers/dma.c | 14 ++++++++++++++ drivers/dma.h | 2 ++ drivers/usart.c | 51 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/drivers/dma.c b/drivers/dma.c index 1cb0f03..1fef4c8 100644 --- a/drivers/dma.c +++ b/drivers/dma.c @@ -133,6 +133,20 @@ void dma_disable(enum DmaPeriph dma, enum DmaChannel channel) } } +uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channel) +{ + switch (dma) { + case DMA_PERIPH_1: + return dma1->CHANNELS[channel].CNDTR.NDT; + break; + case DMA_PERIPH_2: + return dma2->CHANNELS[channel].CNDTR.NDT; + break; + default: + return 0; + break; + } +} //--local functions------------------------------------------------------------- diff --git a/drivers/dma.h b/drivers/dma.h index 05f471e..b5a2159 100644 --- a/drivers/dma.h +++ b/drivers/dma.h @@ -94,6 +94,8 @@ void dma_enable(enum DmaPeriph dma, enum DmaChannel channel); void dma_disable(enum DmaPeriph dma, enum DmaChannel channel); +uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channe); + #endif //_DMA_H_ diff --git a/drivers/usart.c b/drivers/usart.c index 0b8406c..7567c87 100644 --- a/drivers/usart.c +++ b/drivers/usart.c @@ -19,9 +19,12 @@ //--local definitions----------------------------------------------------------- -static volatile struct USART* const usart1 = (struct USART*)USART1_BASE_ADDRESS; -static volatile struct USART* const usart2 = (struct USART*)USART2_BASE_ADDRESS; -static volatile struct USART* const usart3 = (struct USART*)USART3_BASE_ADDRESS; +struct CircularBuffer { + volatile uint8_t* buffer; + uint16_t size; + uint16_t begin; + bool dmaLooped; +}; static void configure_usart(volatile struct USART* regs, enum UsartConfig config); @@ -29,7 +32,7 @@ static void configure_baudrate(volatile struct USART* regs, uint32_t clock, uint32_t baudrate); static uint32_t periph_regs(enum UsartPeriph periph, volatile struct USART** regs); -static uint32_t read_from_buffer(volatile uint8_t* buffer, +static uint32_t read_from_buffer(struct CircularBuffer* buffer, enum DmaChannel channel, uint8_t* byte); static void usart1_rx_callback(enum DmaIRQSource src); @@ -37,7 +40,11 @@ static void usart1_rx_callback(enum DmaIRQSource src); //--local variables------------------------------------------------------------- -static volatile uint8_t* usart1_rx_buffer; +static volatile struct USART* const usart1 = (struct USART*)USART1_BASE_ADDRESS; +static volatile struct USART* const usart2 = (struct USART*)USART2_BASE_ADDRESS; +static volatile struct USART* const usart3 = (struct USART*)USART3_BASE_ADDRESS; + +static struct CircularBuffer usart1_rx_buffer; //--public functions------------------------------------------------------------ @@ -87,13 +94,13 @@ uint32_t usart_write_byte(enum UsartPeriph periph, uint8_t byte) uint32_t usart_read_byte(enum UsartPeriph periph, uint8_t* byte) { volatile struct USART* regs; - volatile uint8_t* buffer; + struct CircularBuffer* buffer; enum DmaChannel dma_channel; switch (periph) { case USART_PERIPH_1: regs = usart1; - buffer = usart1_rx_buffer; + buffer = &usart1_rx_buffer; dma_channel = DMA_CHANNEL_5; break; case USART_PERIPH_2: @@ -103,7 +110,7 @@ uint32_t usart_read_byte(enum UsartPeriph periph, uint8_t* byte) break; } - if (buffer) { + if (buffer->buffer) { return read_from_buffer(buffer, dma_channel, byte); } else { if (regs->SR.RXNE) { @@ -126,7 +133,10 @@ void usart_set_rx_buffer(enum UsartPeriph periph, uint8_t* buffer, | DMA_CONFIG_PSIZE_8BITS | DMA_CONFIG_MSIZE_8BITS | DMA_CONFIG_PRIO_LOW, (void*)&usart1->DR, buffer, size, usart1_rx_callback); - usart1_rx_buffer = buffer; + usart1_rx_buffer.buffer = buffer; + usart1_rx_buffer.size = size; + usart1_rx_buffer.begin = 0; + usart1_rx_buffer.dmaLooped = false; reg_set(usart1->CR3, USART_CR3_DMAR); break; case USART_PERIPH_2: @@ -140,6 +150,7 @@ void usart_set_rx_buffer(enum UsartPeriph periph, uint8_t* buffer, static void configure_usart(volatile struct USART* regs, enum UsartConfig config) { + usart1_rx_buffer.buffer = NULL; //configure parity switch (config) { @@ -247,16 +258,34 @@ static uint32_t periph_regs(enum UsartPeriph periph, volatile struct USART** reg return 0; } -static uint32_t read_from_buffer(volatile uint8_t* buffer, +static uint32_t read_from_buffer(struct CircularBuffer* buffer, enum DmaChannel channel, uint8_t* byte) { + uint16_t end = buffer->size - dma_get_remaining(DMA_PERIPH_1, channel); + if ((end > buffer->begin) && buffer->dmaLooped) { + //TODO overflow + buffer->begin = end; + } else if ((buffer->begin == end) && !buffer->dmaLooped) { + //TODO no data + return 1; + } + + *byte = buffer->buffer[buffer->begin]; + ++buffer->begin; + if (buffer->begin >= buffer->size) { + buffer->begin = 0; + buffer->dmaLooped = false; + } + + return 0; } //--callbacks------------------------------------------------------------------- static void usart1_rx_callback(enum DmaIRQSource src) { - + (void)src; //only transfer complete expected + usart1_rx_buffer.dmaLooped = true; }