mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-21 15:34:33 +08:00
implement UART read state machine
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user