Fixed major UART Issue, I hate it

This commit is contained in:
AlexanderHD27
2025-01-03 12:33:51 +01:00
parent cbf702c6d5
commit 1fd8737fe4
22 changed files with 665 additions and 222 deletions

View File

@@ -1,8 +1,9 @@
add_library(GobotRPC STATIC
${CMAKE_CURRENT_LIST_DIR}/../ctrl_interface/base.cpp
${CMAKE_CURRENT_LIST_DIR}/../ctrl_interface/hardware_rp2040_uart.cpp
${CMAKE_CURRENT_LIST_DIR}/../ctrl_interface/hardware_base.cpp
${CMAKE_CURRENT_LIST_DIR}/../ctrl_interface/uart_rp2040/hardware_rp2040_uart.cpp
${CMAKE_CURRENT_LIST_DIR}/../ctrl_interface/uart_rp2040/rx.cpp
${CMAKE_CURRENT_LIST_DIR}/../crc16.cpp
${CMAKE_CURRENT_LIST_DIR}/../protocol_base.cpp
)
target_include_directories(GobotRPC PUBLIC

View File

@@ -21,10 +21,12 @@ void GobotRPC_CI_rxData_cb(void * args, char *data, size_t len) {
void GobotRPC_CI::onRxData(char *data, size_t len) {
GobotRPC_CI_CMD cmd = (GobotRPC_CI_CMD)data[0];
switch (cmd) {
case TX_CI_PACKET:
if(this->cb_TxPacket != NULL) {
this->cb_TxPacket(this->cb_TxPacket_args, data+1, len-1);
uint32_t addr = (data[2] << 24) | (data[3] << 16) | (data[4] << 8) | data[5];
this->cb_TxPacket(this->cb_TxPacket_args, data+6, len-6, addr);
}
break;
default:
@@ -37,10 +39,16 @@ void GobotRPC_CI::registerCB_TxPacket(callback_TxPacket cb, void *args) {
this->cb_TxPacket_args = args;
}
void GobotRPC_CI::send_RxPacket(char *data, size_t len) {
void GobotRPC_CI::send_RxPacket(char *data, size_t len, uint32_t addr) {
data[0] = RX_CI_PACKET;
data[1] = len + CI_RX_PACKAGE_DATA_OFFSET;
this->hardware->send(data, len+1);
data[2] = (addr >> 24) & 0xff;
data[3] = (addr >> 16) & 0xff;
data[4] = (addr >> 8) & 0xff;
data[5] = addr & 0xff;
this->hardware->send(data, len+6);
}
// Heartbeat Task
@@ -51,9 +59,9 @@ void GobotRPC_CI_heartBeatTaskFn(void *args) {
}
void GobotRPC_CI::heartBeartTaskFn() {
char heartBeatPacket[] = {0xff};
char heartBeatPacket[] = {0xff, 0x02};
while(1) {
this->hardware->send(heartBeatPacket, 1);
this->hardware->send(heartBeatPacket, 2);
vTaskDelay(GOBOTRPC_HEARTBEAT_INTERVAL / portTICK_PERIOD_MS);
}
}

View File

@@ -1,2 +0,0 @@
#include "ctrl_interface_hardware.hpp"

View File

@@ -1,107 +0,0 @@
#include "ctrl_interface_hardware.hpp"
#include "pinConfig.hpp"
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <string.h>
// Initialize stuff
GobotRPC_CI_Hardware_RP2040_UART * g_GobotRPC_CI_Hardware_RP2040_UART;
GobotRPC_CI_Hardware_RP2040_UART::GobotRPC_CI_Hardware_RP2040_UART(uart_inst_t *uart, uint baudrate) {
g_GobotRPC_CI_Hardware_RP2040_UART = this;
emptyInputBuffersQueue = xQueueCreate(NUM_INPUT_BUFFERS, sizeof(inputBuffers_t *));
filledInputBuffersQueue = xQueueCreate(NUM_INPUT_BUFFERS, sizeof(inputBuffers_t *));
for(int i = 0; i < NUM_INPUT_BUFFERS; i++) {
inputBuffers_t * p = &inputBufferPool[i];
memset(p->data, 0xff, 256);
p->len = 0;
xQueueSend(emptyInputBuffersQueue, &p, portMAX_DELAY);
}
txMutex = xSemaphoreCreateMutex();
this->uart = uart;
uart_init(this->uart, baudrate);
gpio_set_function(GOBOTRPC_CI_UART_RX, UART_FUNCSEL_NUM(uart, GOBOTRPC_CI_UART_RX));
gpio_set_function(GOBOTRPC_CI_UART_TX, UART_FUNCSEL_NUM(uart, GOBOTRPC_CI_UART_TX));
uart_set_hw_flow(uart, false, false);
uart_set_format(uart, 8, 1, UART_PARITY_NONE);
uart_set_baudrate(uart, baudrate);
uart_set_fifo_enabled(uart, true);
int UART_IRQ = uart == uart0 ? UART0_IRQ : UART1_IRQ;
irq_set_exclusive_handler(UART_IRQ, GobotRPC_CI_Hardware_RP2040_UART_isr);
irq_set_enabled(UART_IRQ, true);
uart_set_irq_enables(uart, true, false);
xTaskCreate(GobotRPC_CI_Hardware_RP2040_UART_RXTaskFn, "UART RX Task", 2048, this, 4, &this->rxTaskHandle);
}
void GobotRPC_CI_Hardware_RP2040_UART::registerCB_RxData(callback_rxData cb, void *args) {
this->cb_rxData = cb;
this->cb_rxData_args = args;
}
// Sending data
void GobotRPC_CI_Hardware_RP2040_UART::send(char *data, size_t len) {
xSemaphoreTake(txMutex, portMAX_DELAY);
uart_write_blocking(this->uart, (uint8_t *)(data), len);
xSemaphoreGive(txMutex);
}
// Rx ISR
void GobotRPC_CI_Hardware_RP2040_UART_isr() {
GobotRPC_CI_Hardware_RP2040_UART *uart = (GobotRPC_CI_Hardware_RP2040_UART *)g_GobotRPC_CI_Hardware_RP2040_UART;
uart->rxISR();
};
void GobotRPC_CI_Hardware_RP2040_UART::rxISR() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
inputBuffers_t * inputBuffer;
xQueueReceiveFromISR(emptyInputBuffersQueue, &inputBuffer, &xHigherPriorityTaskWoken);
int i;
for(i = 0; uart_is_readable(this->uart) && i < 256; i++) {
volatile uint8_t c = uart_getc(this->uart);
inputBuffer->data[i] = c;
}
inputBuffer->len = i;
xQueueSendFromISR(filledInputBuffersQueue, &inputBuffer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// Rx Task
void GobotRPC_CI_Hardware_RP2040_UART_RXTaskFn(void *args) {
GobotRPC_CI_Hardware_RP2040_UART *uart = (GobotRPC_CI_Hardware_RP2040_UART *)args;
uart->rxTask();
};
void GobotRPC_CI_Hardware_RP2040_UART::rxTask() {
inputBuffers_t * inputBuffer;
while (1) {
xQueueReceive(filledInputBuffersQueue, &inputBuffer, portMAX_DELAY);
if(inputBuffer->len > 0) {
cb_rxData(cb_rxData_args, inputBuffer->data, inputBuffer->len);
}
xQueueSend(emptyInputBuffersQueue, &inputBuffer, portMAX_DELAY);
}
}

View File

@@ -0,0 +1,53 @@
#include "ctrl_interface_hardware.hpp"
#include "pinConfig.hpp"
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <string.h>
// Initialize stuff
GobotRPC_CI_Hardware_RP2040_UART * g_GobotRPC_CI_Hardware_RP2040_UART;
GobotRPC_CI_Hardware_RP2040_UART::GobotRPC_CI_Hardware_RP2040_UART(uart_inst_t *uart, uint baudrate) {
g_GobotRPC_CI_Hardware_RP2040_UART = this;
initRxTaskAndQueues();
txMutex = xSemaphoreCreateMutex();
this->uart = uart;
uart_init(this->uart, baudrate);
gpio_set_function(GOBOTRPC_CI_UART_RX, UART_FUNCSEL_NUM(uart, GOBOTRPC_CI_UART_RX));
gpio_set_function(GOBOTRPC_CI_UART_TX, UART_FUNCSEL_NUM(uart, GOBOTRPC_CI_UART_TX));
uart_set_hw_flow(uart, false, false);
uart_set_format(uart, 8, 1, UART_PARITY_NONE);
uart_set_baudrate(uart, baudrate);
uart_set_fifo_enabled(uart, true);
int UART_IRQ = uart == uart0 ? UART0_IRQ : UART1_IRQ;
irq_set_exclusive_handler(UART_IRQ, GobotRPC_CI_Hardware_RP2040_UART_isr);
irq_set_enabled(UART_IRQ, true);
uart_set_irq_enables(uart, true, false);
}
void GobotRPC_CI_Hardware_RP2040_UART::registerCB_RxData(callback_rxData cb, void *args) {
this->cb_rxData = cb;
this->cb_rxData_args = args;
}
// Sending data
void GobotRPC_CI_Hardware_RP2040_UART::send(char *data, size_t len) {
xSemaphoreTake(txMutex, portMAX_DELAY);
uart_write_blocking(this->uart, (uint8_t *)(data), len);
uart_tx_wait_blocking(this->uart);
xSemaphoreGive(txMutex);
}

View File

@@ -0,0 +1,120 @@
#include "ctrl_interface_hardware.hpp"
#include "pico/stdlib.h"
#include <string.h>
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
// External Functions
void GobotRPC_CI_Hardware_RP2040_UART_isr() {
GobotRPC_CI_Hardware_RP2040_UART *uart = (GobotRPC_CI_Hardware_RP2040_UART *)g_GobotRPC_CI_Hardware_RP2040_UART;
uart->onRx_ISR();
};
void GobotRPC_CI_Hardware_RP2040_UART_Task_RXProcessing(void *args) {
GobotRPC_CI_Hardware_RP2040_UART *uart = (GobotRPC_CI_Hardware_RP2040_UART *)args;
uart->rxProcessingTaskFn();
}
// Init
void GobotRPC_CI_Hardware_RP2040_UART::initRxTaskAndQueues() {
emptyInputBuffersQueue = xQueueCreate(NUM_INPUT_BUFFERS, sizeof(inputBuffers_t *));
filledInputBuffersQueue = xQueueCreate(NUM_INPUT_BUFFERS, sizeof(inputBuffers_t *));
for(int i = 0; i < NUM_INPUT_BUFFERS; i++) {
inputBuffers_t * p = &inputBufferPool[i];
memset(p->data, 0xff, 256);
p->len = 0;
p->state = NEW;
p->expected_length = 0;
xQueueSend(emptyInputBuffersQueue, &p, portMAX_DELAY);
}
rxSignalSemaphore = xSemaphoreCreateBinary();
xTaskCreate(GobotRPC_CI_Hardware_RP2040_UART_Task_RXProcessing, "UART RX Processing", 1024, this, 3, &this->rxProcessingTaskHandle);
}
inputBufferRXState_t fillBuffer(inputBuffers_t * buffer, char data) {
switch(buffer->state) {
case NEW:
buffer->data[0] = data;
buffer->len = 1;
buffer->state = READ_SIZE;
break;
case READ_SIZE:
buffer->data[1] = data;
buffer->expected_length = data;
buffer->len += 1;
if(buffer->len == buffer->expected_length) {
buffer->state = FULL;
} else {
buffer->state = READ_DATA;
}
break;
case READ_DATA:
buffer->data[buffer->len] = data;
buffer->len += 1;
if(buffer->len == buffer->expected_length) {
buffer->state = FULL;
} else {
buffer->state = READ_DATA;
}
break;
case FULL:
break;
}
return buffer->state;
}
// real Task Fns
void GobotRPC_CI_Hardware_RP2040_UART::onRx_ISR() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
static inputBuffers_t * inputBuffer = NULL;
while (uart_is_readable(this->uart)) {
if(inputBuffer == NULL) {
xQueueReceiveFromISR(emptyInputBuffersQueue, &inputBuffer, &xHigherPriorityTaskWoken);
if(inputBuffer == NULL) {
return; // No more buffers -> device overload
}
inputBuffer->state = NEW;
inputBuffer->len = 0;
inputBuffer->expected_length = 0;
}
inputBufferRXState_t state = fillBuffer(inputBuffer, uart_getc(this->uart));
if (state == FULL) {
xQueueSendFromISR(filledInputBuffersQueue, &inputBuffer, &xHigherPriorityTaskWoken);
inputBuffer = NULL;
}
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void GobotRPC_CI_Hardware_RP2040_UART::rxProcessingTaskFn() {
inputBuffers_t * inputBuffer = NULL;
while(1) {
xQueueReceive(filledInputBuffersQueue, &inputBuffer, portMAX_DELAY);
if(this->cb_rxData != NULL) {
this->cb_rxData(this->cb_rxData_args, inputBuffer->data, inputBuffer->len);
}
vTaskDelay(1000);
}
}

View File

@@ -9,7 +9,13 @@ enum GobotRPC_CI_CMD {
SCAN_RESULT_CI_PACKET = 0x04,
};
typedef void (*callback_TxPacket)(void * args, char *data, size_t len);
#define CI_TX_PACKAGE_DATA_OFFSET 6
#define CI_TX_PACKAGE_SIZE(data_len) (data_len + CI_TX_PACKAGE_SIZE)
#define CI_RX_PACKAGE_DATA_OFFSET 6
#define CI_RX_PACKAGE_SIZE(data_len) (data_len + CI_RX_PACKAGE_DATA_OFFSET)
typedef void (*callback_TxPacket)(void * args, char *data, size_t len, uint32_t addr);
void GobotRPC_CI_rxData_cb(void * args, char *data, size_t len);
void GobotRPC_CI_heartBeatTaskFn(void *args);
@@ -26,7 +32,7 @@ public:
GobotRPC_CI(I_GobotRPC_CI_Hardware *hardware);
void registerCB_TxPacket(callback_TxPacket cb, void *args);
void send_RxPacket(char *data, size_t len);
void send_RxPacket(char *data, size_t len, uint32_t addr);
void onRxData(char *data, size_t len);

View File

@@ -19,13 +19,23 @@ public:
#include "hardware/uart.h"
void GobotRPC_CI_Hardware_RP2040_UART_isr();
void GobotRPC_CI_Hardware_RP2040_UART_RXTaskFn(void *args);
void GobotRPC_CI_Hardware_RP2040_UART_Task_RXBuffering(void *args);
void GobotRPC_CI_Hardware_RP2040_UART_Task_RXProcessing(void *args);
#define NUM_INPUT_BUFFERS 16
enum inputBufferRXState_t {
NEW,
READ_SIZE,
READ_DATA,
FULL
};
struct inputBuffers_t {
char data[256];
size_t expected_length;
size_t len;
inputBufferRXState_t state;
};
class GobotRPC_CI_Hardware_RP2040_UART : public I_GobotRPC_CI_Hardware {
@@ -34,22 +44,28 @@ private:
inputBuffers_t inputBufferPool[NUM_INPUT_BUFFERS];
TaskHandle_t rxTaskHandle;
SemaphoreHandle_t txMutex;
TaskHandle_t rxProcessingTaskHandle;
SemaphoreHandle_t rxSignalSemaphore;
QueueHandle_t emptyInputBuffersQueue;
QueueHandle_t filledInputBuffersQueue;
callback_rxData cb_rxData;
void * cb_rxData_args;
SemaphoreHandle_t txMutex;
public:
GobotRPC_CI_Hardware_RP2040_UART(uart_inst_t *uart, uint baudrate);
void send(char *data, size_t len) override;
void registerCB_RxData(callback_rxData cb, void *args);
void rxISR();
void rxTask();
void initRxTaskAndQueues();
void onRx_ISR();
void rxBufferingTaskFn();
void rxProcessingTaskFn();
};
extern GobotRPC_CI_Hardware_RP2040_UART * g_GobotRPC_CI_Hardware_RP2040_UART;

View File

@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include <strings.h>
enum GobotRPCNumber {
VACUM = 0x8
};
enum GobotRPCTypes {
REQUEST = 0b00,
RESPONSE = 0b01,
ERROR = 0b10
};
#define GobotRPC_Package_DATA_OFFSET 2
#define CALC_SIZE_GobotRPC_PACKAGE(data_len) (data_len + GobotRPC_Package_DATA_OFFSET + 2)
struct GobotRPCHeaderInfo {
public:
GobotRPCNumber number;
GobotRPCTypes type;
size_t len;
};
void assembleGobotRPCHeader(char * buffer, GobotRPCNumber number, GobotRPCTypes data_size, size_t);
void assembleCRC(char * buffer, size_t data_len);
GobotRPCHeaderInfo extractGobotRPCHeader(char * buffer);

View File

@@ -0,0 +1,25 @@
#include "protocol.hpp"
#include <stdint.h>
#include "pico/stdlib.h"
#include "crc16.hpp"
void assembleGobotRPCHeader(char * buffer, GobotRPCNumber number, GobotRPCTypes type, size_t len) {
buffer[0] = ((number & 0b1111) << 4) | ((type & 0b11) << 2);
buffer[1] = (len + 4) & 0xff;
}
GobotRPCHeaderInfo extractGobotRPCHeader(char * buffer) {
GobotRPCHeaderInfo info;
info.number = (GobotRPCNumber)((buffer[0] >> 4) & 0b1111);
info.type = (GobotRPCTypes)((buffer[0] >> 2) & 0b11);
info.len = buffer[1];
return info;
}
void assembleCRC(char * buffer, size_t data_len) {
unsigned short crc = crc16(buffer, data_len + GobotRPC_Package_DATA_OFFSET);
buffer[GobotRPC_Package_DATA_OFFSET + data_len + 1] = crc & 0xff;
buffer[GobotRPC_Package_DATA_OFFSET + data_len + 0] = (crc >> 8) & 0xff;
}

View File

@@ -8,7 +8,7 @@
#include "FreeRTOS.h"
#include "task.h"
#include "crc16.hpp"
#include "protocol.hpp"
#define LED_PIN 25
@@ -21,16 +21,16 @@ void vTaskMain(void * pvParameters) {
}
}
void onTxPacket(void * args, char *data, size_t len) {
void onTxPacket(void * args, char *data, size_t len, uint32_t addr) {
GobotRPC_CI * gobotRPC_ci = (GobotRPC_CI *)args;
char buffer[] = {0x00, 0x74, 0x04, 0x00, 0x00};
unsigned short crc = crc16(buffer + 1, 2);
char bufferPackage[CI_RX_PACKAGE_SIZE(CALC_SIZE_GobotRPC_PACKAGE(0))];
char * gorpcPackageOffset = bufferPackage + CI_RX_PACKAGE_DATA_OFFSET;
buffer[4] = crc & 0xff;
buffer[3] = (crc >> 8) & 0xff;
assembleGobotRPCHeader(gorpcPackageOffset, GobotRPCNumber::VACUM, GobotRPCTypes::RESPONSE, 0);
assembleCRC(gorpcPackageOffset, 0);
gobotRPC_ci->send_RxPacket(buffer, 4);
gobotRPC_ci->send_RxPacket(bufferPackage, CALC_SIZE_GobotRPC_PACKAGE(0), addr);
}
int main() {