Document USART's private functions
This commit is contained in:
parent
fdc5f381f8
commit
b9285f2ab9
@ -21,20 +21,20 @@
|
|||||||
//--local definitions-----------------------------------------------------------
|
//--local definitions-----------------------------------------------------------
|
||||||
|
|
||||||
struct CircularBuffer {
|
struct CircularBuffer {
|
||||||
volatile uint8_t* buffer;
|
volatile uint8_t* buffer; //the buffer to use as a circular buffer
|
||||||
uint16_t size;
|
uint16_t size; //the size of the buffer
|
||||||
uint16_t begin;
|
uint16_t begin; //pointer to the current begin of the buffer
|
||||||
bool dmaLooped;
|
bool dmaLooped; //whether the DMA looped or not (buffer overflow)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FragmentedBuffer {
|
struct FragmentedBuffer {
|
||||||
uint8_t** buffers;
|
uint8_t** buffers; //list of buffers to write to
|
||||||
uint16_t buffer_size;
|
uint16_t buffer_size; //size of a single buffer
|
||||||
uint16_t byte_index;
|
uint16_t byte_index; //index of the current byte in the current buffer
|
||||||
uint8_t buffer_nb;
|
uint8_t buffer_nb; //total number of buffers
|
||||||
uint8_t free_buffer_nb;
|
uint8_t free_buffer_nb; //number of buffers not currently used
|
||||||
uint8_t buffer_index;
|
uint8_t buffer_index; //index of the current buffer
|
||||||
uint8_t dma_buffer_index;
|
uint8_t dma_buffer_index; //index of the DMA's current buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
static void configure_usart(volatile struct USART* regs,
|
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-------------------------------------------------------------
|
//--local functions-------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the given configuration to the given registers. Generic version of
|
||||||
|
* usart_configure()
|
||||||
|
*/
|
||||||
static void configure_usart(volatile struct USART* regs,
|
static void configure_usart(volatile struct USART* regs,
|
||||||
enum UsartConfig config)
|
enum UsartConfig config)
|
||||||
{
|
{
|
||||||
@ -279,6 +283,11 @@ static void configure_usart(volatile struct USART* regs,
|
|||||||
reg_set(regs->CR1, USART_CR1_UE);
|
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,
|
static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
|
||||||
uint32_t baudrate)
|
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);
|
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)
|
static uint32_t write_byte(volatile struct USART* regs, uint8_t byte)
|
||||||
{
|
{
|
||||||
|
//write if TX register empty
|
||||||
if (regs->SR.TXE) {
|
if (regs->SR.TXE) {
|
||||||
reg_write(regs->DR, USART_DR_DR, byte);
|
reg_write(regs->DR, USART_DR_DR, byte);
|
||||||
|
//enable IRQ, disable DMA
|
||||||
reg_reset(regs->CR3, USART_CR3_DMAT);
|
reg_reset(regs->CR3, USART_CR3_DMAT);
|
||||||
reg_set(regs->CR1, USART_CR1_TXEIE);
|
reg_set(regs->CR1, USART_CR1_TXEIE);
|
||||||
nvic_enable(NVIC_IRQ_USART1);
|
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,
|
static uint32_t write_to_buffer(volatile struct USART *regs,
|
||||||
volatile struct FragmentedBuffer *buffer, enum DmaChannel channel,
|
volatile struct FragmentedBuffer *buffer, enum DmaChannel channel,
|
||||||
uint8_t byte)
|
uint8_t byte)
|
||||||
@ -335,6 +355,7 @@ static uint32_t write_to_buffer(volatile struct USART *regs,
|
|||||||
dma_enter_critical(DMA_PERIPH_1, channel);
|
dma_enter_critical(DMA_PERIPH_1, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//write the byte
|
||||||
buffer->buffers[buffer->buffer_index][buffer->byte_index] = byte;
|
buffer->buffers[buffer->buffer_index][buffer->byte_index] = byte;
|
||||||
++buffer->byte_index;
|
++buffer->byte_index;
|
||||||
|
|
||||||
@ -342,11 +363,17 @@ static uint32_t write_to_buffer(volatile struct USART *regs,
|
|||||||
return 0;
|
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,
|
static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
|
||||||
enum DmaChannel channel, uint8_t* byte)
|
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);
|
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) {
|
if ((end > buffer->begin) && buffer->dmaLooped) {
|
||||||
//TODO overflow
|
//TODO overflow
|
||||||
buffer->begin = end;
|
buffer->begin = end;
|
||||||
@ -355,6 +382,7 @@ static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//read the oldest byte and advance the buffer
|
||||||
*byte = buffer->buffer[buffer->begin];
|
*byte = buffer->buffer[buffer->begin];
|
||||||
++buffer->begin;
|
++buffer->begin;
|
||||||
if (buffer->begin >= buffer->size) {
|
if (buffer->begin >= buffer->size) {
|
||||||
@ -367,11 +395,16 @@ static uint32_t read_from_buffer(volatile struct CircularBuffer* buffer,
|
|||||||
|
|
||||||
//--callbacks-------------------------------------------------------------------
|
//--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)
|
static void usart1_tx_callback(enum DmaIRQSource src)
|
||||||
{
|
{
|
||||||
(void)src; //only transfer complete expected
|
(void)src; //only transfer complete expected
|
||||||
volatile struct FragmentedBuffer* buffer = &usart1_tx_buffer;
|
volatile struct FragmentedBuffer* buffer = &usart1_tx_buffer;
|
||||||
|
|
||||||
|
//increment DMA's buffer since the last once has already been sent
|
||||||
++buffer->dma_buffer_index;
|
++buffer->dma_buffer_index;
|
||||||
if (buffer->dma_buffer_index >= buffer->buffer_nb) {
|
if (buffer->dma_buffer_index >= buffer->buffer_nb) {
|
||||||
buffer->dma_buffer_index = 0;
|
buffer->dma_buffer_index = 0;
|
||||||
@ -384,6 +417,7 @@ static void usart1_tx_callback(enum DmaIRQSource src)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//else start a new transfer
|
||||||
dma_configure(DMA_PERIPH_1, DMA_CHANNEL_4,
|
dma_configure(DMA_PERIPH_1, DMA_CHANNEL_4,
|
||||||
DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM
|
DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM
|
||||||
| DMA_CONFIG_INC_MEM | DMA_CONFIG_PSIZE_8BITS
|
| DMA_CONFIG_INC_MEM | DMA_CONFIG_PSIZE_8BITS
|
||||||
@ -393,6 +427,8 @@ static void usart1_tx_callback(enum DmaIRQSource src)
|
|||||||
buffer->byte_index,
|
buffer->byte_index,
|
||||||
usart1_tx_callback);
|
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)
|
if (buffer->dma_buffer_index == buffer->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)
|
static void usart1_rx_callback(enum DmaIRQSource src)
|
||||||
{
|
{
|
||||||
(void)src; //only transfer complete expected
|
(void)src; //only transfer complete expected
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user