Document USART's private functions

This commit is contained in:
Steins7 2023-09-16 17:38:13 +02:00
parent fdc5f381f8
commit b9285f2ab9

View File

@ -21,20 +21,20 @@
//--local definitions-----------------------------------------------------------
struct CircularBuffer {
volatile uint8_t* buffer;
uint16_t size;
uint16_t begin;
bool dmaLooped;
volatile uint8_t* buffer; //the buffer to use as a circular buffer
uint16_t size; //the size of the buffer
uint16_t begin; //pointer to the current begin of the buffer
bool dmaLooped; //whether the DMA looped or not (buffer overflow)
};
struct FragmentedBuffer {
uint8_t** buffers;
uint16_t buffer_size;
uint16_t byte_index;
uint8_t buffer_nb;
uint8_t free_buffer_nb;
uint8_t buffer_index;
uint8_t dma_buffer_index;
uint8_t** buffers; //list of buffers to write to
uint16_t buffer_size; //size of a single buffer
uint16_t byte_index; //index of the current byte in the current buffer
uint8_t buffer_nb; //total number of buffers
uint8_t free_buffer_nb; //number of buffers not currently used
uint8_t buffer_index; //index of the current buffer
uint8_t dma_buffer_index; //index of the DMA's current buffer
};
static void configure_usart(volatile struct USART* regs,
@ -202,6 +202,10 @@ void usart_set_rx_buffer(enum UsartPeriph periph, uint8_t* buffer,
//--local functions-------------------------------------------------------------
/**
* Apply the given configuration to the given registers. Generic version of
* usart_configure()
*/
static void configure_usart(volatile struct USART* regs,
enum UsartConfig config)
{
@ -279,6 +283,11 @@ static void configure_usart(volatile struct USART* regs,
reg_set(regs->CR1, USART_CR1_UE);
}
/**
* Configure the given registers with the given baudrate. Baudrate is dependant
* on the peripheric's clock and may not be exact due to precision errors (see
* table 192 in documentation)
*/
static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
uint32_t baudrate)
{
@ -292,10 +301,17 @@ static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
reg_write(regs->BRR, USART_BRR_DIV_Fraction, divider & 0xF);
}
/**
* Non-blocking write to the given USART. Will return 0 if the write was
* successfull, 1 otherwise. If the write is successfull, the tranfer complete
* IRQ is enabled and the DMA disabled
*/
static uint32_t write_byte(volatile struct USART* regs, uint8_t byte)
{
//write if TX register empty
if (regs->SR.TXE) {
reg_write(regs->DR, USART_DR_DR, byte);
//enable IRQ, disable DMA
reg_reset(regs->CR3, USART_CR3_DMAT);
reg_set(regs->CR1, USART_CR1_TXEIE);
nvic_enable(NVIC_IRQ_USART1);
@ -305,6 +321,10 @@ static uint32_t write_byte(volatile struct USART* regs, uint8_t byte)
}
}
/**
* Writes the given byte to the given UART, using a FragmentedBuffer and a DMA
* to bufferize the write if the peripheral is already busy.
*/
static uint32_t write_to_buffer(volatile struct USART *regs,
volatile struct FragmentedBuffer *buffer, enum DmaChannel channel,
uint8_t byte)
@ -335,6 +355,7 @@ static uint32_t write_to_buffer(volatile struct USART *regs,
dma_enter_critical(DMA_PERIPH_1, channel);
}
//write the byte
buffer->buffers[buffer->buffer_index][buffer->byte_index] = byte;
++buffer->byte_index;
@ -342,11 +363,17 @@ static uint32_t write_to_buffer(volatile struct USART *regs,
return 0;
}
/**
* Reads the oldest byte from the given CircularBuffer if any. Returns 0 if the
* read was successfull, 1 otherwise
*/
static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
enum DmaChannel channel, uint8_t* byte)
{
//retreive the current end of the buffer based on the DMA's progress
uint16_t end = buffer->size - dma_get_remaining(DMA_PERIPH_1, channel);
//check for bytes to read and overflow
if ((end > buffer->begin) && buffer->dmaLooped) {
//TODO overflow
buffer->begin = end;
@ -355,6 +382,7 @@ static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
return 1;
}
//read the oldest byte and advance the buffer
*byte = buffer->buffer[buffer->begin];
++buffer->begin;
if (buffer->begin >= buffer->size) {
@ -367,11 +395,16 @@ static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
//--callbacks-------------------------------------------------------------------
/**
* Callback called on DMA TX tranfert's completion. Checks for any remaining
* data to send. If any, starts a new transfer, else stop the DMA
*/
static void usart1_tx_callback(enum DmaIRQSource src)
{
(void)src; //only transfer complete expected
volatile struct FragmentedBuffer* buffer = &usart1_tx_buffer;
//increment DMA's buffer since the last once has already been sent
++buffer->dma_buffer_index;
if (buffer->dma_buffer_index >= buffer->buffer_nb) {
buffer->dma_buffer_index = 0;
@ -384,6 +417,7 @@ static void usart1_tx_callback(enum DmaIRQSource src)
return;
}
//else start a new transfer
dma_configure(DMA_PERIPH_1, DMA_CHANNEL_4,
DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM
| DMA_CONFIG_INC_MEM | DMA_CONFIG_PSIZE_8BITS
@ -393,6 +427,8 @@ static void usart1_tx_callback(enum DmaIRQSource src)
buffer->byte_index,
usart1_tx_callback);
//if the newly transfering buffer was being written to, switch the current
//buffer. Since we just ended a transfer, the next buffer should be empty
if (buffer->dma_buffer_index == buffer->buffer_index)
{
++buffer->buffer_index;
@ -403,6 +439,10 @@ static void usart1_tx_callback(enum DmaIRQSource src)
}
}
/**
* Callback called on DMA RX tranfert's completion. Sets a flag needed to
* properly handle the circular buffer
*/
static void usart1_rx_callback(enum DmaIRQSource src)
{
(void)src; //only transfer complete expected