forked from achamaikin/CCSModuleSW30Web
almost done dma
This commit is contained in:
+89
-67
@@ -11,6 +11,9 @@ ISR_FAST static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_
|
||||
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;
|
||||
|
||||
@@ -20,11 +23,9 @@ 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;
|
||||
static uint32_t sc_uart2_last_recover_tick = 0;
|
||||
|
||||
#define SC_UART2_REINIT_TIMEOUT_MS 500u
|
||||
#define SC_UART2_RECOVER_GUARD_MS 200u
|
||||
#define SC_UART2_PACKET_TIMEOUT_MS 5000u
|
||||
|
||||
StatusPacket_t statusPacket = {
|
||||
@@ -85,34 +86,26 @@ void SC_Init() {
|
||||
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;
|
||||
sc_uart2_last_recover_tick = sc_uart2_last_packet_tick;
|
||||
SC_ArmUart2RxDma();
|
||||
SC_ArmUart5RxDma();
|
||||
}
|
||||
|
||||
void SC_Task() {
|
||||
static uint32_t tick;
|
||||
if ((int32_t)(HAL_GetTick() - tick) < 1) return;
|
||||
tick = HAL_GetTick();
|
||||
SC_UART2_Watchdog();
|
||||
|
||||
// Запуск приема в режиме прерывания с ожиданием idle
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Запуск приема в режиме 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
|
||||
}
|
||||
}
|
||||
@@ -120,34 +113,37 @@ void SC_Task() {
|
||||
// Проверка наличия принятой команды для обработки
|
||||
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
|
||||
// HAL_Delay(2);
|
||||
SC_CommandHandler(&serial_control.received_command);
|
||||
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);
|
||||
}
|
||||
SC_CommandHandler((ReceivedCommand_t*)&serial_control.received_command);
|
||||
serial_control.command_ready = 0; // Сбрасываем флаг
|
||||
SC_ArmUart2RxDma();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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_reinit_tick = sc_uart2_last_packet_tick;
|
||||
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;
|
||||
HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
SC_ArmUart2RxDma();
|
||||
} else if (huart->Instance == huart5.Instance) {
|
||||
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);
|
||||
}
|
||||
HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
||||
SC_ArmUart5RxDma();
|
||||
} else if (huart->Instance == huart3.Instance) {
|
||||
CCS_RxEventCallback(huart, Size);
|
||||
}
|
||||
@@ -155,8 +151,9 @@ ISR_FAST void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Siz
|
||||
|
||||
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;
|
||||
} else if (huart->Instance == huart3.Instance) {
|
||||
CCS_TxCpltCallback(huart);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,16 +214,14 @@ ISR_FAST void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_
|
||||
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);
|
||||
|
||||
sc_uart2_rx_during_tx = 0u;
|
||||
|
||||
HAL_UART_Transmit_IT(&huart2, serial_control.tx_buffer, packet_len);
|
||||
|
||||
serial_control.tx_tick = HAL_GetTick();
|
||||
}
|
||||
@@ -276,39 +271,66 @@ ISR_FAST static uint8_t process_received_packet(SerialControl_t *ctx, const uint
|
||||
|
||||
static void SC_UART2_Watchdog(void) {
|
||||
const uint32_t now = HAL_GetTick();
|
||||
const uint32_t since_last_packet = now - sc_uart2_last_packet_tick;
|
||||
const int32_t since_last_packet = (int32_t)(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 (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 ((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");
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user