Overwrite repository contents with fork state.

Replace outdated files with the latest working tree from fork/CCSModuleSW30Web to align source and generated artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-09 13:16:13 +03:00
parent 28d63c7270
commit e8b3ed90cd
50 changed files with 35096 additions and 27560 deletions
+134 -77
View File
@@ -3,14 +3,17 @@
#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);
static void SC_ArmUart2Rx(void);
static void SC_ArmUart5Rx(void);
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);
static void SC_ArmUart2RxDma(void);
static void SC_ArmUart5RxDma(void);
static void SC_LogUartError(const char *tag, UART_HandleTypeDef *huart);
uint8_t test_crc_invalid = 0;
@@ -18,6 +21,12 @@ 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_recover_tick = 0;
#define SC_UART2_RECOVER_GUARD_MS 200u
#define SC_UART2_PACKET_TIMEOUT_MS 5000u
StatusPacket_t statusPacket = {
.SOC = 0,
@@ -75,100 +84,83 @@ 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_recover_tick = sc_uart2_last_packet_tick;
SC_ArmUart2RxDma();
SC_ArmUart5RxDma();
}
void SC_Task() {
// Запуск приема в режиме прерывания с ожиданием idle
SC_ArmUart2Rx();
SC_ArmUart5Rx();
static uint32_t tick;
if ((int32_t)(HAL_GetTick() - tick) < 1) return;
tick = HAL_GetTick();
SC_UART2_Watchdog();
// Запуск приема в режиме DMA + idle
SC_ArmUart2RxDma();
SC_ArmUart5RxDma();
// Проверка таймаута отправки пакета (больше 100 мс)
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0) {
if ((HAL_GetTick() - serial_control.tx_tick) > 100) {
if ((int32_t)(HAL_GetTick() - serial_control.tx_tick) > 100) {
// Таймаут: принудительно сбрасываем передачу
HAL_UART_Abort_IT(&huart2);
// Выключаем DIR при сбросе передачи
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
(void)HAL_UART_AbortTransmit(&huart2);
serial_control.tx_tick = 0; // Сбрасываем tick
}
}
// Проверка наличия принятой команды для обработки
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
g_sc_command_source = SC_SOURCE_UART2;
SC_CommandHandler(&serial_control.received_command);
// HAL_Delay(2);
SC_CommandHandler((ReceivedCommand_t*)&serial_control.received_command);
serial_control.command_ready = 0; // Сбрасываем флаг
SC_ArmUart2Rx();
}
if (serial_control.response_pending && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
SC_SendPacket(NULL, 0, serial_control.response_code);
serial_control.response_pending = 0;
}
if (serial_iso.command_ready) {
g_sc_command_source = SC_SOURCE_UART5;
SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
serial_iso.command_ready = 0;
SC_ArmUart5Rx();
SC_ArmUart2RxDma();
}
}
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 (!process_received_packet(&serial_control, serial_control.rx_buffer, Size)) {
serial_control.response_pending = 1;
serial_control.response_code = RESP_INVALID;
SC_ArmUart2Rx();
if (Size == 0u) {
log_printf(LOG_WARN, "UART2 RX idle event with zero size\n");
}
sc_uart2_last_packet_tick = HAL_GetTick();
sc_uart2_last_recover_tick = sc_uart2_last_packet_tick;
sc_uart2_timed_out = 0;
if(!process_received_packet(&serial_control, serial_control.rx_buffer, Size)){
log_printf(LOG_WARN, "UART2 RX invalid packet len=%u\n", (unsigned)Size);
SC_SendPacket(NULL, 0, RESP_INVALID);
}
g_sc_command_source = SC_SOURCE_UART2;
SC_ArmUart2RxDma();
} else if (huart->Instance == huart5.Instance) {
if (!process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
SC_ArmUart5Rx();
if (Size == 0u) {
log_printf(LOG_WARN, "UART5 RX idle event with zero size\n");
}
if (process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
g_sc_command_source = SC_SOURCE_UART5;
SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
} else {
log_printf(LOG_WARN, "UART5 RX invalid packet len=%u\n", (unsigned)Size);
}
SC_ArmUart5RxDma();
} else if (huart->Instance == huart3.Instance) {
CCS_RxEventCallback(huart, Size);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
ISR_FAST void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == huart2.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "USART2 rx error: 0x%08lx\n", uart_error);
SC_ArmUart2Rx();
} else if (huart->Instance == huart5.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "UART5 rx error: 0x%08lx\n", uart_error);
SC_ArmUart5Rx();
} else if (huart->Instance == huart3.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "USART3 rx error: 0x%08lx\n", uart_error);
CCS_RxArm();
}
}
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;
}
}
static void SC_ArmUart2Rx(void) {
if ((&huart2)->RxState == HAL_UART_STATE_READY && serial_control.command_ready == 0) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
}
static void SC_ArmUart5Rx(void) {
if ((&huart5)->RxState == HAL_UART_STATE_READY && serial_iso.command_ready == 0) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
} else if (huart->Instance == huart3.Instance) {
CCS_TxCpltCallback(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++) {
@@ -185,7 +177,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;
@@ -218,24 +210,24 @@ 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) {
if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
HAL_UART_Abort_IT(&huart2);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
if (huart2.gState != HAL_UART_STATE_READY) {
(void)HAL_UART_AbortTransmit(&huart2);
log_printf(LOG_WARN, "UART2 TX busy, abort transmit before resend\n");
}
if (HAL_UART_Transmit_DMA(&huart2, serial_control.tx_buffer, packet_len) != HAL_OK) {
SC_LogUartError("UART2 TX DMA start failed", &huart2);
return;
}
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
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;
@@ -268,7 +260,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;
}
@@ -277,3 +269,68 @@ 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 int32_t since_last_packet = (int32_t)(now - sc_uart2_last_packet_tick);
if (since_last_packet >= (int32_t)SC_UART2_PACKET_TIMEOUT_MS) {
if (sc_uart2_timed_out == 0u) {
serial_control.command_ready = 0;
log_printf(LOG_WARN, "UART2 RX packet timeout (%u ms)\n", (unsigned)SC_UART2_PACKET_TIMEOUT_MS);
}
sc_uart2_timed_out = 1;
} else {
sc_uart2_timed_out = 0;
}
if ((huart2.RxState == HAL_UART_STATE_READY) &&
((int32_t)(now - sc_uart2_last_recover_tick) >= (int32_t)SC_UART2_RECOVER_GUARD_MS)) {
SC_ArmUart2RxDma();
sc_uart2_last_recover_tick = now;
}
}
static void SC_ArmUart2RxDma(void) {
if ((huart2.RxState == HAL_UART_STATE_READY) && (serial_control.command_ready == 0)) {
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1) != HAL_OK) {
SC_LogUartError("UART2 RX DMA arm failed", &huart2);
}
}
}
static void SC_ArmUart5RxDma(void) {
if (huart5.RxState == HAL_UART_STATE_READY) {
if (HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1) == HAL_OK) {
return;
}
SC_LogUartError("UART5 RX IT arm failed", &huart5);
}
}
void SC_RecoverUartDma(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
SC_LogUartError("UART2 recover start", &huart2);
(void)HAL_UART_AbortReceive(&huart2);
(void)HAL_UART_AbortTransmit(&huart2);
serial_control.tx_tick = 0;
SC_ArmUart2RxDma();
sc_uart2_last_recover_tick = HAL_GetTick();
} else if (huart == &huart5) {
SC_LogUartError("UART5 recover start", &huart5);
(void)HAL_UART_AbortReceive(&huart5);
SC_ArmUart5RxDma();
}
}
static void SC_LogUartError(const char *tag, UART_HandleTypeDef *huart) {
if (tag == NULL || huart == NULL) {
return;
}
log_printf(LOG_ERR, "%s: instance=0x%08lx err=0x%08lx g=%lu rx=%lu\n",
tag,
(unsigned long)huart->Instance,
(unsigned long)HAL_UART_GetError(huart),
(unsigned long)huart->gState,
(unsigned long)huart->RxState);
}