Init
This commit is contained in:
parent
1ee101a5c9
commit
d8261599fe
|
|
@ -29,6 +29,7 @@ typedef struct {
|
||||||
lin_frame_t rxFrame;
|
lin_frame_t rxFrame;
|
||||||
osMessageQueueId_t rxDataQueue;
|
osMessageQueueId_t rxDataQueue;
|
||||||
osMessageQueueId_t rxDataSnifferQueue;
|
osMessageQueueId_t rxDataSnifferQueue;
|
||||||
|
bool linTxInProgress; // Флаг передачи
|
||||||
} tSerialPortLinArtery;
|
} tSerialPortLinArtery;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ void vSerialPortLinInit(
|
||||||
) {
|
) {
|
||||||
env->uart = uart;
|
env->uart = uart;
|
||||||
|
|
||||||
env->linLastByteTime = 10;
|
env->linLastByteTime = 2;
|
||||||
env->linFrameTimeoutMs = 10;
|
env->linFrameTimeoutMs = 2;
|
||||||
|
|
||||||
usart_reset(uart);
|
usart_reset(uart);
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ void vSerialPortLinInit(
|
||||||
// Включаем прерывание по break frame
|
// Включаем прерывание по break frame
|
||||||
usart_interrupt_enable(uart, USART_BF_INT, TRUE);
|
usart_interrupt_enable(uart, USART_BF_INT, TRUE);
|
||||||
usart_interrupt_enable(uart, USART_RDBF_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_EnableIRQ(irq);
|
||||||
NVIC_SetPriority(irq, irqPriority);
|
NVIC_SetPriority(irq, irqPriority);
|
||||||
|
|
@ -122,68 +122,11 @@ static uint8_t LIN_CalcParity(uint8_t id) {
|
||||||
return (p1 << 7) | (p0 << 6);
|
return (p1 << 7) | (p0 << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Измененный обработчик прерываний (без IDLE):
|
extern const uint8_t DRS_SENSON_ADR_Stat[8];
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Выделенная функция обработки кадра
|
// Выделенная функция обработки кадра
|
||||||
static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) {
|
static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env, bool isHeader) {
|
||||||
// Проверка sync field
|
// Проверка sync field
|
||||||
if (env->linBuffer[0] != 0x55) {
|
if (env->linBuffer[0] != 0x55) {
|
||||||
env->rxFrame.event = LIN_SYNC_ERROR;
|
env->rxFrame.event = LIN_SYNC_ERROR;
|
||||||
|
|
@ -202,6 +145,14 @@ static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) {
|
||||||
return;
|
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.id = id;
|
||||||
env->rxFrame.dataLen = env->linByteCount - 3;
|
env->rxFrame.dataLen = env->linByteCount - 3;
|
||||||
|
|
||||||
|
|
@ -233,10 +184,121 @@ static void LIN_ProcessReceivedFrame(tSerialPortLinArtery *env) {
|
||||||
osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0);
|
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 мс)
|
// Функция проверки таймаута (вызывать из таймера, например, каждые 1-5 мс)
|
||||||
void LIN_CheckTimeout(tSerialPortLinArtery *env) {
|
void LIN_CheckTimeout(tSerialPortLinArtery *env) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
if (!env->linFrameStarted) {
|
if (!env->linFrameStarted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -246,9 +308,20 @@ void LIN_CheckTimeout(tSerialPortLinArtery *env) {
|
||||||
|
|
||||||
if (elapsed >= env->linFrameTimeoutMs) {
|
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 {
|
} else {
|
||||||
// Недостаточно данных
|
// Недостаточно данных
|
||||||
env->rxFrame.event = LIN_TIMEOUT;
|
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) {
|
static bool vSerialPortSendLinFrame(tSerialPortLinArtery *env, const lin_frame_t *pFrame, uint32_t timeout) {
|
||||||
uint8_t txBuffer[11]; // Максимальный размер LIN кадра (без break)
|
uint8_t txBuffer[11]; // Максимальный размер LIN кадра (без break)
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
|
|
@ -289,23 +362,73 @@ static bool vSerialPortSendLinFrame(tSerialPortLinArtery *env, const lin_frame_t
|
||||||
// Checksum
|
// Checksum
|
||||||
txBuffer[idx++] = pFrame->checksum;
|
txBuffer[idx++] = pFrame->checksum;
|
||||||
|
|
||||||
// 2. Отправка break field
|
env->linTxInProgress = true;
|
||||||
|
|
||||||
|
// 1. Отправка break field
|
||||||
usart_break_send(env->uart);
|
usart_break_send(env->uart);
|
||||||
|
|
||||||
// Ожидание завершения отправки break
|
// Ожидаем завершения break (но не через TDC!)
|
||||||
uint32_t breakTimeout = SystemGetMs() + 10; // 10мс максимум на break
|
uint32_t breakTimeout = SystemGetMs() + 2; // 2мс достаточно для break
|
||||||
while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET) {
|
while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET) {
|
||||||
if (SystemGetMs() > breakTimeout) {
|
if (SystemGetMs() > breakTimeout) {
|
||||||
|
env->linTxInProgress = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Отправка данных (возвращает количество отправленных байт)
|
// 2. Отправка данных (используем TDBE, не TDC!)
|
||||||
uint16_t sent = vSerialPortLinTransmitOverCore(env, txBuffer, idx, timeout);
|
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,
|
static uint16_t vSerialPortLinReceiveQueue(tSerialPortLinArtery *env, uint8_t *data, uint16_t size, uint32_t timeout,
|
||||||
osMessageQueueId_t queueId) {
|
osMessageQueueId_t queueId) {
|
||||||
|
|
@ -350,10 +473,21 @@ static uint8_t vLinTransmitCommand(tSerialPortLinArtery *env, tLinData *linData,
|
||||||
txFrame.data[i] = linData->g_aTxBuffer[i];
|
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) {
|
if (result) {
|
||||||
return LIN_RX_COMPLETED;
|
return LIN_TX_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LIN_TIMEOUT;
|
return LIN_TIMEOUT;
|
||||||
|
|
@ -368,10 +502,12 @@ static uint8_t vLinReceivedCommand(tSerialPortLinArtery *env, tLinData *linData,
|
||||||
|
|
||||||
memset(linData->g_aRxBuffer, 0, sizeof(linData->g_aRxBuffer));
|
memset(linData->g_aRxBuffer, 0, sizeof(linData->g_aRxBuffer));
|
||||||
|
|
||||||
linData->g_aRxBufferLen = rxFrame.dataLen + 1;
|
if (rxFrame.event == LIN_RX_COMPLETED) {
|
||||||
linData->g_aRxBuffer[0] = rxFrame.id;
|
linData->g_aRxBufferLen = rxFrame.dataLen + 1;
|
||||||
for (uint8_t i = 0; i < rxFrame.dataLen; ++i) {
|
linData->g_aRxBuffer[0] = rxFrame.id;
|
||||||
linData->g_aRxBuffer[i + 1] = rxFrame.data[i];
|
for (uint8_t i = 0; i < rxFrame.dataLen; ++i) {
|
||||||
|
linData->g_aRxBuffer[i + 1] = rxFrame.data[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rxFrame.event;
|
return rxFrame.event;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue