further improve hardware independence

This commit is contained in:
Samuel Sadok
2020-07-21 12:55:10 +02:00
parent 71cc825ba2
commit b3ddadb360
22 changed files with 358 additions and 266 deletions
+19 -16
View File
@@ -22,10 +22,12 @@ static uint32_t dma_last_rcv_idx;
// static thread_local uint32_t deadline_ms = 0;
osThreadId uart_thread;
extern UART_HandleTypeDef* uart0;
static UART_HandleTypeDef* huart_ = uart0; // defined in board.cpp.
const uint32_t stack_size_uart_thread = 4096; // Bytes
class UART4Sender : public StreamSink {
class UARTSender : public StreamSink {
public:
int process_bytes(const uint8_t* buffer, size_t length, size_t* processed_bytes) {
// Loop to ensure all bytes get sent
@@ -38,7 +40,7 @@ public:
return -1;
// transmit chunk
memcpy(tx_buf_, buffer, chunk);
if (HAL_UART_Transmit_DMA(&huart4, tx_buf_, chunk) != HAL_OK)
if (HAL_UART_Transmit_DMA(huart_, tx_buf_, chunk) != HAL_OK)
return -1;
buffer += chunk;
length -= chunk;
@@ -51,12 +53,12 @@ public:
size_t get_free_space() { return SIZE_MAX; }
private:
uint8_t tx_buf_[UART_TX_BUFFER_SIZE];
} uart4_stream_output;
StreamSink* uart4_stream_output_ptr = &uart4_stream_output;
} uart_stream_output;
StreamSink* uart_stream_output_ptr = &uart_stream_output;
StreamBasedPacketSink uart4_packet_output(uart4_stream_output);
BidirectionalPacketBasedChannel uart4_channel(uart4_packet_output);
StreamToPacketSegmenter uart4_stream_input(uart4_channel);
StreamBasedPacketSink uart_packet_output(uart_stream_output);
BidirectionalPacketBasedChannel uart_channel(uart_packet_output);
StreamToPacketSegmenter uart_stream_input(uart_channel);
static void uart_server_thread(void * ctx) {
(void) ctx;
@@ -65,13 +67,13 @@ static void uart_server_thread(void * ctx) {
osDelay(1);
// Check for UART errors and restart recieve DMA transfer if required
if (huart4.RxState != HAL_UART_STATE_BUSY_RX) {
HAL_UART_AbortReceive(&huart4);
HAL_UART_Receive_DMA(&huart4, dma_rx_buffer, sizeof(dma_rx_buffer));
if (huart_->RxState != HAL_UART_STATE_BUSY_RX) {
HAL_UART_AbortReceive(huart_);
HAL_UART_Receive_DMA(huart_, dma_rx_buffer, sizeof(dma_rx_buffer));
dma_last_rcv_idx = 0;
}
// Fetch the circular buffer "write pointer", where it would write next
uint32_t new_rcv_idx = UART_RX_BUFFER_SIZE - huart4.hdmarx->Instance->NDTR;
uint32_t new_rcv_idx = UART_RX_BUFFER_SIZE - huart_->hdmarx->Instance->NDTR;
if (new_rcv_idx > UART_RX_BUFFER_SIZE) { // defensive programming
continue;
}
@@ -79,27 +81,28 @@ static void uart_server_thread(void * ctx) {
// deadline_ms = timeout_to_deadline(PROTOCOL_SERVER_TIMEOUT_MS);
// Process bytes in one or two chunks (two in case there was a wrap)
if (new_rcv_idx < dma_last_rcv_idx) {
uart4_stream_input.process_bytes(dma_rx_buffer + dma_last_rcv_idx,
uart_stream_input.process_bytes(dma_rx_buffer + dma_last_rcv_idx,
UART_RX_BUFFER_SIZE - dma_last_rcv_idx, nullptr); // TODO: use process_all
ASCII_protocol_parse_stream(dma_rx_buffer + dma_last_rcv_idx,
UART_RX_BUFFER_SIZE - dma_last_rcv_idx, uart4_stream_output);
UART_RX_BUFFER_SIZE - dma_last_rcv_idx, uart_stream_output);
dma_last_rcv_idx = 0;
}
if (new_rcv_idx > dma_last_rcv_idx) {
uart4_stream_input.process_bytes(dma_rx_buffer + dma_last_rcv_idx,
uart_stream_input.process_bytes(dma_rx_buffer + dma_last_rcv_idx,
new_rcv_idx - dma_last_rcv_idx, nullptr); // TODO: use process_all
ASCII_protocol_parse_stream(dma_rx_buffer + dma_last_rcv_idx,
new_rcv_idx - dma_last_rcv_idx, uart4_stream_output);
new_rcv_idx - dma_last_rcv_idx, uart_stream_output);
dma_last_rcv_idx = new_rcv_idx;
}
};
}
// TODO: allow multiple UART server instances
void start_uart_server() {
// 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_rx_buffer, sizeof(dma_rx_buffer));
HAL_UART_Receive_DMA(huart_, dma_rx_buffer, sizeof(dma_rx_buffer));
dma_last_rcv_idx = 0;
// Start UART communication thread