latest version before merge
This commit is contained in:
+90
-14
@@ -2,12 +2,15 @@
|
||||
#include "usart.h"
|
||||
#include "board.h"
|
||||
#include "serial.h"
|
||||
#include "debug.h"
|
||||
#include "isr_opt.h"
|
||||
|
||||
// Приватные функции
|
||||
static uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
|
||||
static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code);
|
||||
static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd);
|
||||
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len);
|
||||
ISR_FAST static uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
|
||||
ISR_FAST static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code);
|
||||
ISR_FAST static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd);
|
||||
ISR_FAST static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len);
|
||||
static void SC_UART2_Watchdog(void);
|
||||
|
||||
uint8_t test_crc_invalid = 0;
|
||||
|
||||
@@ -15,6 +18,14 @@ SerialControl_t serial_control;
|
||||
// Контекст для приема пакетов по UART5 (однонаправленный UART)
|
||||
static SerialControl_t serial_iso;
|
||||
volatile SC_Source_t g_sc_command_source = SC_SOURCE_UART2;
|
||||
static volatile uint8_t sc_uart2_timed_out = 0;
|
||||
static uint32_t sc_uart2_last_packet_tick = 0;
|
||||
static uint32_t sc_uart2_last_reinit_tick = 0;
|
||||
/** Событие приёма по UART2 при активной передаче (см. HAL_UARTEx_RxEventCallback / SC_UART2_Watchdog). */
|
||||
static volatile uint8_t sc_uart2_rx_during_tx = 0;
|
||||
|
||||
#define SC_UART2_REINIT_TIMEOUT_MS 500u
|
||||
#define SC_UART2_PACKET_TIMEOUT_MS 5000u
|
||||
|
||||
StatusPacket_t statusPacket = {
|
||||
.SOC = 0,
|
||||
@@ -72,12 +83,28 @@ void SC_Init() {
|
||||
// Обнуляем структуру
|
||||
memset(&serial_control, 0, sizeof(SerialControl_t));
|
||||
memset(&serial_iso, 0, sizeof(serial_iso));
|
||||
sc_uart2_timed_out = 0;
|
||||
sc_uart2_last_packet_tick = HAL_GetTick();
|
||||
sc_uart2_last_reinit_tick = sc_uart2_last_packet_tick;
|
||||
sc_uart2_rx_during_tx = 0;
|
||||
}
|
||||
|
||||
void SC_Task() {
|
||||
SC_UART2_Watchdog();
|
||||
|
||||
// Запуск приема в режиме прерывания с ожиданием idle
|
||||
if((huart2.RxState == HAL_UART_STATE_READY) && (serial_control.command_ready == 0)) HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
if((huart5.RxState == HAL_UART_STATE_READY)) HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
if ((huart2.RxState == HAL_UART_STATE_READY) && (serial_control.command_ready == 0)) {
|
||||
if ((HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
|
||||
(HAL_UART_GetError(&huart2) != HAL_UART_ERROR_NONE)) {
|
||||
(void)HAL_UART_Abort_IT(&huart2);
|
||||
}
|
||||
}
|
||||
if (huart5.RxState == HAL_UART_STATE_READY) {
|
||||
if ((HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
|
||||
(HAL_UART_GetError(&huart5) != HAL_UART_ERROR_NONE)) {
|
||||
(void)HAL_UART_Abort_IT(&huart5);
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка таймаута отправки пакета (больше 100 мс)
|
||||
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0) {
|
||||
@@ -94,13 +121,22 @@ void SC_Task() {
|
||||
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
|
||||
// HAL_Delay(2);
|
||||
SC_CommandHandler(&serial_control.received_command);
|
||||
HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
if ((HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) &&
|
||||
(HAL_UART_GetError(&huart2) != HAL_UART_ERROR_NONE)) {
|
||||
(void)HAL_UART_Abort_IT(&huart2);
|
||||
}
|
||||
serial_control.command_ready = 0; // Сбрасываем флаг
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
|
||||
ISR_FAST void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
|
||||
if (huart->Instance == huart2.Instance) {
|
||||
if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
|
||||
sc_uart2_rx_during_tx = 1u;
|
||||
}
|
||||
sc_uart2_last_packet_tick = HAL_GetTick();
|
||||
sc_uart2_last_reinit_tick = sc_uart2_last_packet_tick;
|
||||
sc_uart2_timed_out = 0;
|
||||
if(!process_received_packet(&serial_control, serial_control.rx_buffer, Size)){
|
||||
SC_SendPacket(NULL, 0, RESP_INVALID);
|
||||
}
|
||||
@@ -117,7 +153,7 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
ISR_FAST void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
if (huart->Instance == huart2.Instance) {
|
||||
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
||||
serial_control.tx_tick = 0;
|
||||
@@ -127,7 +163,7 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
// Приватные функции реализации
|
||||
|
||||
// Полностью программная реализация CRC-32 (полином CRC32_POLYNOMIAL, порядок little-endian)
|
||||
static uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
|
||||
ISR_FAST static uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
|
||||
uint32_t crc = 0xFFFFFFFFu;
|
||||
|
||||
for (uint16_t i = 0; i < length; i++) {
|
||||
@@ -144,7 +180,7 @@ static uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
|
||||
return crc ^ 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code) {
|
||||
ISR_FAST static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code) {
|
||||
uint16_t out_index = 0;
|
||||
|
||||
output[out_index++] = response_code;
|
||||
@@ -177,7 +213,7 @@ static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint
|
||||
return out_index;
|
||||
}
|
||||
|
||||
void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code) {
|
||||
ISR_FAST void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code) {
|
||||
uint16_t packet_len = encode_packet(payload, payload_len, serial_control.tx_buffer, response_code);
|
||||
|
||||
if (packet_len > 0) {
|
||||
@@ -188,13 +224,15 @@ void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t respons
|
||||
|
||||
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
|
||||
|
||||
sc_uart2_rx_during_tx = 0u;
|
||||
|
||||
HAL_UART_Transmit_IT(&huart2, serial_control.tx_buffer, packet_len);
|
||||
|
||||
serial_control.tx_tick = HAL_GetTick();
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd) {
|
||||
ISR_FAST static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd) {
|
||||
// if (test_crc_invalid && (packet_data[1] != CMD_GET_STATUS)) {
|
||||
// test_crc_invalid--;
|
||||
// return 0;
|
||||
@@ -227,7 +265,7 @@ static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, Rec
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len) {
|
||||
ISR_FAST static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len) {
|
||||
if (!parse_packet(packet_data, packet_len, (ReceivedCommand_t *)&ctx->received_command)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -236,3 +274,41 @@ static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* pack
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void SC_UART2_Watchdog(void) {
|
||||
const uint32_t now = HAL_GetTick();
|
||||
const uint32_t since_last_packet = now - sc_uart2_last_packet_tick;
|
||||
|
||||
if ((huart2.gState == HAL_UART_STATE_BUSY_TX) && (sc_uart2_rx_during_tx != 0u)) {
|
||||
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
||||
(void)HAL_UART_Abort_IT(&huart2);
|
||||
(void)HAL_UART_DeInit(&huart2);
|
||||
(void)HAL_UART_Init(&huart2);
|
||||
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
serial_control.tx_tick = 0;
|
||||
sc_uart2_rx_during_tx = 0u;
|
||||
sc_uart2_last_reinit_tick = now;
|
||||
log_printf(LOG_ERR, "USART2 BUSY_TX: hard reinit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (since_last_packet >= SC_UART2_PACKET_TIMEOUT_MS) {
|
||||
if (sc_uart2_timed_out == 0u) {
|
||||
serial_control.command_ready = 0;
|
||||
}
|
||||
sc_uart2_timed_out = 1;
|
||||
} else {
|
||||
sc_uart2_timed_out = 0;
|
||||
}
|
||||
|
||||
if ((since_last_packet >= SC_UART2_REINIT_TIMEOUT_MS) &&
|
||||
((now - sc_uart2_last_reinit_tick) >= SC_UART2_REINIT_TIMEOUT_MS)) {
|
||||
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
||||
(void)HAL_UART_Abort_IT(&huart2);
|
||||
(void)HAL_UART_DeInit(&huart2);
|
||||
(void)HAL_UART_Init(&huart2);
|
||||
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
sc_uart2_last_reinit_tick = now;
|
||||
log_printf(LOG_ERR, "USART2 stalled: hard reinit\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user