diff --git a/Inc/SerialPortLinArtery.h b/Inc/SerialPortLinArtery.h index d7adb26..a5b3d6e 100644 --- a/Inc/SerialPortLinArtery.h +++ b/Inc/SerialPortLinArtery.h @@ -29,6 +29,7 @@ typedef struct { lin_frame_t rxFrame; osMessageQueueId_t rxDataQueue; osMessageQueueId_t rxDataSnifferQueue; + bool linTxInProgress; // Флаг передачи } tSerialPortLinArtery; diff --git a/Src/SerialPortLinArtery.c b/Src/SerialPortLinArtery.c index f933a40..06ab911 100644 --- a/Src/SerialPortLinArtery.c +++ b/Src/SerialPortLinArtery.c @@ -19,8 +19,8 @@ void vSerialPortLinInit( ) { env->uart = uart; - env->linLastByteTime = 10; - env->linFrameTimeoutMs = 10; + env->linLastByteTime = 2; + env->linFrameTimeoutMs = 2; usart_reset(uart); @@ -45,7 +45,7 @@ void vSerialPortLinInit( // Включаем прерывание по break frame usart_interrupt_enable(uart, USART_BF_INT, TRUE); usart_interrupt_enable(uart, USART_RDBF_INT, TRUE); -// usart_interrupt_enable(uart, USART_IDLE_INT, TRUE); + usart_interrupt_enable(uart, USART_IDLE_INT, TRUE); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); @@ -122,68 +122,11 @@ static uint8_t LIN_CalcParity(uint8_t id) { return (p1 << 7) | (p0 << 6); } -// Измененный обработчик прерываний (без IDLE): -void SerialPort_IrqProcessing_UartLin(tSerialPortLinArtery *env) { - - // 1. Break frame detection - - if (usart_flag_get(env->uart, USART_BFF_FLAG)) { - usart_flag_clear(env->uart, USART_BFF_FLAG); - usart_data_receive(env->uart); - - env->linFrameStarted = true; - env->linByteCount = 0; - env->linLastByteTime = SystemGetMs(); // Запоминаем время - env->rxFrame.event = LIN_RECV_BREAK_FIELD_OK; - return; - } - - - // 2. Receive data (без IDLE) - if (usart_flag_get(env->uart, USART_RDBF_FLAG)) { - - uint8_t data = usart_data_receive(env->uart); - - if (env->linFrameStarted && (env->linByteCount < sizeof(env->linBuffer))) { - env->linBuffer[env->linByteCount] = data; - env->linByteCount++; - env->linLastByteTime = SystemGetMs(); // Обновляем время - } else { - if (env->linFrameStarted) { - env->rxFrame.event = LIN_RX_OVERRUN; - osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); - env->linFrameStarted = false; - } - } - } - - // 3. Error handling - if (usart_flag_get(env->uart, USART_FERR_FLAG)) { - usart_flag_clear(env->uart, USART_FERR_FLAG); - usart_data_receive(env->uart); - - if (env->linFrameStarted) { - env->rxFrame.event = LIN_FRAME_ERROR; - osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); - env->linFrameStarted = false; - } - } - - if (usart_flag_get(env->uart, USART_ROERR_FLAG)) { - usart_flag_clear(env->uart, USART_ROERR_FLAG); - usart_data_receive(env->uart); - - if (env->linFrameStarted) { - env->rxFrame.event = LIN_RX_OVERRUN; - osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); - env->linFrameStarted = false; - } - } -} +extern const uint8_t DRS_SENSON_ADR_Stat[8]; // Выделенная функция обработки кадра -static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) { +static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env, bool isHeader) { // Проверка sync field if (env->linBuffer[0] != 0x55) { env->rxFrame.event = LIN_SYNC_ERROR; @@ -202,6 +145,14 @@ static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) { return; } + if (isHeader) { + env->rxFrame.id = id; + env->rxFrame.dataLen = 0; + env->rxFrame.event = LIN_RX_COMPLETED; + osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); + } + + env->rxFrame.id = id; env->rxFrame.dataLen = env->linByteCount - 3; @@ -233,10 +184,121 @@ static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) { osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); } +// Измененный обработчик прерываний (без IDLE): +void SerialPort_IrqProcessing_UartLin(tSerialPortLinArtery *env) { + + // ИГНОРИРУЕМ ВСЕ ПРЕРЫВАНИЯ ВО ВРЕМЯ ПЕРЕДАЧИ + if (env->linTxInProgress) { + // Просто очищаем флаги, но не обрабатываем + if (usart_flag_get(env->uart, USART_BFF_FLAG)) { + usart_flag_clear(env->uart, USART_BFF_FLAG); + usart_data_receive(env->uart); + } + if (usart_flag_get(env->uart, USART_RDBF_FLAG)) { + usart_data_receive(env->uart); + } + return; + } + + // 1. Break frame detection + + if (usart_flag_get(env->uart, USART_BFF_FLAG)) { + usart_flag_clear(env->uart, USART_BFF_FLAG); + usart_data_receive(env->uart); + + env->linFrameStarted = true; + env->linByteCount = 0; + env->linLastByteTime = SystemGetMs(); // Запоминаем время + env->rxFrame.event = LIN_RECV_BREAK_FIELD_OK; + return; + } + + + if (usart_flag_get(env->uart, USART_IDLEF_FLAG)) { + usart_flag_clear(env->uart, USART_IDLEF_FLAG); + + uint8_t data = usart_data_receive(env->uart); + + if (!env->linFrameStarted) { + return; + } + + // Таймаут - кадр должен быть завершен + if (env->linByteCount >= 2) { + + if (env->linBuffer[1] == 0x97) { + return; + } + + // Пытаемся обработать полученные данные + if (env->linByteCount == 2) { + LIN_ProcessReceivedFrame(env, true); + } else { + LIN_ProcessReceivedFrame(env, false); + } + + } else { + // Недостаточно данных + env->rxFrame.event = LIN_TIMEOUT; + osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); + } + + env->linFrameStarted = false; + + + } + + + + // 2. Receive data (без IDLE) + if (usart_flag_get(env->uart, USART_RDBF_FLAG)) { + + uint8_t data = usart_data_receive(env->uart); + + if (env->linFrameStarted && (env->linByteCount < sizeof(env->linBuffer))) { + env->linBuffer[env->linByteCount] = data; + env->linByteCount++; + env->linLastByteTime = SystemGetMs(); // Обновляем время + } else { + if (env->linFrameStarted) { + env->rxFrame.event = LIN_RX_OVERRUN; + osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); + env->linFrameStarted = false; + } + } + } + + + // 3. Error handling + if (usart_flag_get(env->uart, USART_FERR_FLAG)) { + usart_flag_clear(env->uart, USART_FERR_FLAG); + usart_data_receive(env->uart); + + if (env->linFrameStarted) { + env->rxFrame.event = LIN_FRAME_ERROR; + osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); + env->linFrameStarted = false; + } + } + + if (usart_flag_get(env->uart, USART_ROERR_FLAG)) { + usart_flag_clear(env->uart, USART_ROERR_FLAG); + usart_data_receive(env->uart); + + if (env->linFrameStarted) { + env->rxFrame.event = LIN_RX_OVERRUN; + osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); + env->linFrameStarted = false; + } + } +} + // Функция проверки таймаута (вызывать из таймера, например, каждые 1-5 мс) void LIN_CheckTimeout(tSerialPortLinArtery *env) { + return; + if (!env->linFrameStarted) { return; } @@ -246,9 +308,20 @@ void LIN_CheckTimeout(tSerialPortLinArtery *env) { if (elapsed >= env->linFrameTimeoutMs) { // Таймаут - кадр должен быть завершен - if (env->linByteCount >= 3) { + if (env->linByteCount >= 2) { + + if (env->linBuffer[1] == 0x97) { + return; + } + // Пытаемся обработать полученные данные - LIN_ProcessReceivedFrame(env); + if (env->linByteCount == 2) { + LIN_ProcessReceivedFrame(env, true); + } else { + LIN_ProcessReceivedFrame(env, false); + } + + } else { // Недостаточно данных env->rxFrame.event = LIN_TIMEOUT; @@ -259,7 +332,7 @@ void LIN_CheckTimeout(tSerialPortLinArtery *env) { } } - +/* static bool vSerialPortSendLinFrame(tSerialPortLinArtery *env, const lin_frame_t *pFrame, uint32_t timeout) { uint8_t txBuffer[11]; // Максимальный размер LIN кадра (без break) uint8_t idx = 0; @@ -289,23 +362,73 @@ static bool vSerialPortSendLinFrame(tSerialPortLinArtery *env, const lin_frame_t // Checksum txBuffer[idx++] = pFrame->checksum; - // 2. Отправка break field + env->linTxInProgress = true; + + // 1. Отправка break field usart_break_send(env->uart); - // Ожидание завершения отправки break - uint32_t breakTimeout = SystemGetMs() + 10; // 10мс максимум на break + // Ожидаем завершения break (но не через TDC!) + uint32_t breakTimeout = SystemGetMs() + 2; // 2мс достаточно для break while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET) { if (SystemGetMs() > breakTimeout) { + env->linTxInProgress = false; return false; } } - // 3. Отправка данных (возвращает количество отправленных байт) - uint16_t sent = vSerialPortLinTransmitOverCore(env, txBuffer, idx, timeout); + // 2. Отправка данных (используем TDBE, не TDC!) + for (uint8_t i = 0; i < idx; i++) { + // Ждем пока буфер передачи освободится + while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET); - return (sent == idx); // Успех, если все байты отправлены + // Отправляем байт + usart_data_transmit(env->uart, txBuffer[i]); + + // НЕ ждем TDC! Сразу переходим к следующему байту + } + + // 3. Ждем завершения передачи последнего байта + while (usart_flag_get(env->uart, USART_TDC_FLAG) == RESET); + + env->linTxInProgress = false; + + // 4. Очищаем эхо (важно!) + while (usart_flag_get(env->uart, USART_RDBF_FLAG)) { + (void)usart_data_receive(env->uart); + } + + return true; } +*/ +// Функция отправки RESPONSE от Slave (после получения HEADER) +static bool vSerialPortSendLinResponse(tSerialPortLinArtery *env, const lin_frame_t *pFrame, uint32_t timeout) { + uint8_t txBuffer[10]; // Только данные + checksum (без break и sync!) + uint8_t idx = 0; + + if (!pFrame || pFrame->dataLen > 8) return false; + + // Формируем ТОЛЬКО RESPONSE (без Header!) + for (uint8_t i = 0; i < pFrame->dataLen; i++) { + txBuffer[idx++] = pFrame->data[i]; + } + + txBuffer[idx++] = pFrame->checksum; + + env->linTxInProgress = true; + + // Отправка response (без break и sync!) + for (uint8_t i = 0; i < idx; i++) { + while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET); + usart_data_transmit(env->uart, txBuffer[i]); + } + + // Ждем завершения + while (usart_flag_get(env->uart, USART_TDC_FLAG) == RESET); + + env->linTxInProgress = false; + return true; +} static uint16_t vSerialPortLinReceiveQueue(tSerialPortLinArtery *env, uint8_t *data, uint16_t size, uint32_t timeout, osMessageQueueId_t queueId) { @@ -350,10 +473,21 @@ static uint8_t vLinTransmitCommand(tSerialPortLinArtery *env, tLinData *linData, txFrame.data[i] = linData->g_aTxBuffer[i]; } - bool result = vSerialPortSendLinFrame(env, &txFrame, timeout); + uint8_t receivedPid = linData->g_aRxBuffer[0]; + uint8_t id = receivedPid & 0x3F; + uint8_t expectedPid = id | LIN_CalcParity(id); + + txFrame.id = expectedPid; + txFrame.checksum = LIN_DrvMakeCheckSum( + txFrame.data, + txFrame.dataLen, + txFrame.id + ); + + bool result = vSerialPortSendLinResponse(env, &txFrame, timeout); if (result) { - return LIN_RX_COMPLETED; + return LIN_TX_COMPLETED; } return LIN_TIMEOUT; @@ -368,10 +502,12 @@ static uint8_t vLinReceivedCommand(tSerialPortLinArtery *env, tLinData *linData, memset(linData->g_aRxBuffer, 0, sizeof(linData->g_aRxBuffer)); - linData->g_aRxBufferLen = rxFrame.dataLen + 1; - linData->g_aRxBuffer[0] = rxFrame.id; - for (uint8_t i = 0; i < rxFrame.dataLen; ++i) { - linData->g_aRxBuffer[i + 1] = rxFrame.data[i]; + if (rxFrame.event == LIN_RX_COMPLETED) { + linData->g_aRxBufferLen = rxFrame.dataLen + 1; + linData->g_aRxBuffer[0] = rxFrame.id; + for (uint8_t i = 0; i < rxFrame.dataLen; ++i) { + linData->g_aRxBuffer[i + 1] = rxFrame.data[i]; + } } return rxFrame.event;