implement UART read state machine

This commit is contained in:
Oskar Weigl
2017-09-23 20:31:43 -07:00
parent b82bb9a0c2
commit 9abec8af00
2 changed files with 59 additions and 1 deletions
+1
View File
@@ -51,6 +51,7 @@ C_SOURCES = \
Src/stm32f4xx_hal_msp.c \
Src/can.c \
Src/usart.c \
Src/dma.c \
Src/usbd_conf.c \
Src/usbd_desc.c \
Src/usb_device.c \
+58 -1
View File
@@ -54,6 +54,7 @@
/* USER CODE BEGIN Includes */
#include "freertos_vars.h"
#include "low_level.h"
#include "usart.h"
#include "version.h"
/* USER CODE END Includes */
@@ -142,6 +143,7 @@ void StartDefaultTask(void const * argument)
/* USER CODE BEGIN Application */
//TODO move this to a different file
// Thread to handle deffered processing of USB interrupt
void usb_cmd_thread(void const * argument) {
@@ -152,7 +154,62 @@ void usb_cmd_thread(void const * argument) {
// check for end-char
// checksum, etc.
#define UART_BUFFER_SIZE 64
static uint8_t dma_circ_buffer[UART_BUFFER_SIZE];
static uint8_t parse_buffer[UART_BUFFER_SIZE];
// DMA is set up to recieve in a circular buffer forever.
// We dont use interrupts to fetch the data, instead we periodically read
// data out of the circular buffer into a parse buffer, controlled by a state machine
HAL_UART_Receive_DMA(&huart4, dma_circ_buffer, sizeof(dma_circ_buffer));
uint32_t last_rcv_idx = UART_BUFFER_SIZE - huart4.hdmarx->Instance->NDTR;
// Re-run state-machine forever
for (;;) {
//Inialize recieve state machine
bool reset_read_state = false;
bool read_active = false;
uint32_t parse_buffer_idx = 0;
//Run state machine until reset
do {
// Fetch the circular buffer "write pointer", where it would write next
uint32_t rcv_idx = UART_BUFFER_SIZE - huart4.hdmarx->Instance->NDTR;
// During sleeping, we may have fallen several characters behind, so we keep
// going until we are caught up, before we sleep again
while (rcv_idx != last_rcv_idx) {
// Fetch the next char, rotate read ptr
uint8_t c = dma_circ_buffer[last_rcv_idx];
if (++last_rcv_idx == UART_BUFFER_SIZE)
last_rcv_idx = 0;
// Look for start character
if (c == '$') {
read_active = true;
continue; // do not record start char
}
// Record into parse buffer when actively reading
if (read_active) {
parse_buffer[parse_buffer_idx++] = c;
if (c == '\r' || c == '\n') {
// End of command string: exchange end char with terminating null
parse_buffer[parse_buffer_idx-1] = '\0';
osDelay(1);
// Reset receieve state machine
reset_read_state = true;
break;
} else if (parse_buffer_idx == UART_BUFFER_SIZE - 1) {
// We are not at end of command, and receiving another character after this
// would go into the last slot, which is reserved for terminating null.
// We have effectively overflowed parse buffer: abort.
reset_read_state = true;
break;
}
}
}
// When we reach here, we are out of immediate characters to fetch out of buffer
// So we sleep for a bit.
osDelay(1);
} while (!reset_read_state);
}
for (;;) {
// Wait for signalling from USB interrupt (OTG_FS_IRQHandler)