Init
This commit is contained in:
parent
1ee101a5c9
commit
d8261599fe
|
|
@ -29,6 +29,7 @@ typedef struct {
|
|||
lin_frame_t rxFrame;
|
||||
osMessageQueueId_t rxDataQueue;
|
||||
osMessageQueueId_t rxDataSnifferQueue;
|
||||
bool linTxInProgress; // Флаг передачи
|
||||
} tSerialPortLinArtery;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue