// // Created by cfif on 16.09.22. // #include #include "SerialPortArtery.h" #include "string.h" void vSerialPortInit( tSerialPortArtery *env, usart_type *uart, bool swap, uint32_t BoundRate, IRQn_Type irq, crm_periph_clock_type uartClock, uint8_t irqPriority, uint32_t rxBufferLength, uint32_t rxSnifferLength ) { usart_reset(uart); crm_periph_clock_enable(uartClock, TRUE); usart_init(uart, BoundRate, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); if (swap) { usart_transmit_receive_pin_swap(uart, TRUE); } usart_enable(uart, TRUE); usart_interrupt_enable(uart, USART_RDBF_INT, TRUE); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL); if (rxSnifferLength) { env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL); } else { env->rxDataSnifferQueue = 0; } env->uart = uart; } void vSerialPortLinInit( tSerialPortArtery *env, usart_type *uart, bool swap, uint32_t BoundRate, IRQn_Type irq, crm_periph_clock_type uartClock, uint8_t irqPriority, uint32_t rxBufferLength, uint32_t rxSnifferLength ) { env->uart = uart; env->linLastByteTime = 20; env->linFrameTimeoutMs = 20; usart_reset(uart); crm_periph_clock_enable(uartClock, TRUE); usart_init(uart, BoundRate, USART_DATA_8BITS, USART_STOP_1_BIT); // ВКЛЮЧАЕМ LIN РЕЖИМ!!! usart_lin_mode_enable(uart, TRUE); // Настраиваем длину break field (LIN требует 13 бит, выбираем 11) usart_break_bit_num_set(uart, USART_BREAK_11BITS); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); if (swap) { usart_transmit_receive_pin_swap(uart, TRUE); } usart_enable(uart, TRUE); // Включаем прерывание по 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); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); env->rxDataQueue = osMessageQueueNew(rxBufferLength, 12, NULL); if (rxSnifferLength) { env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, sizeof(lin_frame_t), NULL); } else { env->rxDataSnifferQueue = 0; } } void vSerialPortInitExt( tSerialPortArtery *env, usart_type *uart, bool swap, usart_hardware_flow_control_type flow_control_type, uint32_t BoundRate, IRQn_Type irq, crm_periph_clock_type uartClock, uint8_t irqPriority, uint32_t rxBufferLength, uint32_t rxSnifferLength ) { usart_reset(uart); crm_periph_clock_enable(uartClock, TRUE); usart_init(uart, BoundRate, USART_DATA_8BITS, USART_STOP_1_BIT); usart_hardware_flow_control_set(uart, flow_control_type); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); if (swap) { usart_transmit_receive_pin_swap(uart, TRUE); } usart_enable(uart, TRUE); usart_interrupt_enable(uart, USART_RDBF_INT, TRUE); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL); if (rxSnifferLength) { env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL); } else { env->rxDataSnifferQueue = 0; } env->uart = uart; } void vSerialPortInitDMA( tSerialPortArtery *env, usart_type *uart, dma_type *DMA_RX, dma_type *DMA_TX, dma_channel_type *RX_DMA_CHANNEL, dmamux_channel_type *RX_DMA_CHANNEL_MUX, dmamux_requst_id_sel_type RX_DMAMUX_DMAREQ_ID, IRQn_Type RX_DMA_Channel_IRQ, uint32_t RX_DMA_FDT_FLAG, uint8_t *DMA_BUF, uint16_t DMA_BUF_LEN, dma_channel_type *TX_DMA_CHANNEL, dmamux_channel_type *TX_DMA_CHANNEL_MUX, dmamux_requst_id_sel_type TX_DMAMUX_DMAREQ_ID, IRQn_Type TX_DMA_Channel_IRQ, uint32_t TX_DMA_FDT_FLAG, bool swap, uint32_t BoundRate, IRQn_Type irq, crm_periph_clock_type uartClock, uint8_t irqPriority, uint32_t rxBufferLength, uint32_t rxSnifferLength ) { { if (DMA_RX)NVIC_DisableIRQ(RX_DMA_Channel_IRQ); if (DMA_TX)NVIC_DisableIRQ(TX_DMA_Channel_IRQ); NVIC_DisableIRQ(irq); } /*включаем тактирование uart и нужных DMA */{ crm_periph_clock_enable(uartClock, TRUE); if (DMA_RX == DMA1 || DMA_TX == DMA1) { crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); } if (DMA_RX == DMA2 || DMA_TX == DMA2) { crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE); } } /*заполняем параметры и создаем все очереди до начала работы порта (иначе при раннем сробатывании прервывания все упадет)*/{ env->txAccessQueue = osMessageQueueNew(1, 1, NULL); env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL); if (rxSnifferLength) { env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL); } else { env->rxDataSnifferQueue = 0; } env->rxDmaFdtFlag = RX_DMA_FDT_FLAG; env->txDmaFdtFlag = TX_DMA_FDT_FLAG; env->txDmaChannel = TX_DMA_CHANNEL; env->rxDmaChannel = RX_DMA_CHANNEL; env->rxDmaBuf = DMA_BUF; env->rxDmaOffset = 0; } /*инициализируем uart */{ env->uart = uart; usart_reset(uart); usart_init(uart, BoundRate, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); usart_dma_receiver_enable(uart, TRUE); usart_dma_transmitter_enable(uart, TRUE); if (swap) { usart_transmit_receive_pin_swap(uart, TRUE); } } /*инициализируем RX DMA в циклическом режиме*/if (DMA_RX) { dmamux_enable(DMA_RX, TRUE); // dma channel for usart rx configuration dma_reset(RX_DMA_CHANNEL); dma_default_para_init(&env->dma_rx_init_struct); env->dma_rx_init_struct.buffer_size = DMA_BUF_LEN; env->dma_rx_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; env->dma_rx_init_struct.memory_base_addr = (uint32_t) DMA_BUF; env->dma_rx_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; env->dma_rx_init_struct.memory_inc_enable = TRUE; env->dma_rx_init_struct.peripheral_base_addr = (uint32_t) &uart->dt; env->dma_rx_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; env->dma_rx_init_struct.peripheral_inc_enable = FALSE; env->dma_rx_init_struct.priority = DMA_PRIORITY_HIGH; env->dma_rx_init_struct.loop_mode_enable = TRUE; dma_init(RX_DMA_CHANNEL, &env->dma_rx_init_struct); // config flexible dma for usart7 rx dmamux_init(RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID); } /*инициализируем TX DMA*/if (DMA_TX) { dmamux_enable(DMA_TX, TRUE); // dma channel for usart tx configuration dma_reset(TX_DMA_CHANNEL); dma_default_para_init(&env->dma_tx_init_struct); env->dma_tx_init_struct.buffer_size = 0; env->dma_tx_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; env->dma_tx_init_struct.memory_base_addr = 0; env->dma_tx_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; env->dma_tx_init_struct.memory_inc_enable = TRUE; env->dma_tx_init_struct.peripheral_base_addr = (uint32_t) &uart->dt; env->dma_tx_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; env->dma_tx_init_struct.peripheral_inc_enable = FALSE; env->dma_tx_init_struct.priority = DMA_PRIORITY_HIGH; env->dma_tx_init_struct.loop_mode_enable = FALSE; dma_init(TX_DMA_CHANNEL, &env->dma_tx_init_struct); // config flexible dma for usart7 tx dmamux_init(TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID); } /*включаем rx dma и прерывания на нем*/if (DMA_RX) { dma_interrupt_enable(RX_DMA_CHANNEL, DMA_FDT_INT, TRUE); NVIC_EnableIRQ(RX_DMA_Channel_IRQ); NVIC_SetPriority(RX_DMA_Channel_IRQ, irqPriority); dma_channel_enable(RX_DMA_CHANNEL, TRUE); // uart7 rx begin dma receiving } /*включаем прерывания на tx dma*/if (DMA_TX) { dma_interrupt_enable(TX_DMA_CHANNEL, DMA_FDT_INT, TRUE); NVIC_EnableIRQ(TX_DMA_Channel_IRQ); NVIC_SetPriority(TX_DMA_Channel_IRQ, irqPriority); } /*включаем uart и прерывания на нем*/{ usart_interrupt_enable(uart, USART_IDLE_INT, TRUE); // usart_interrupt_enable(uart, USART_RDBF_INT, FALSE); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); usart_enable(uart, TRUE); } } void vSerialPortInitDMAExt( tSerialPortArtery *env, usart_type *uart, dma_type *DMA_RX, dma_type *DMA_TX, dma_channel_type *RX_DMA_CHANNEL, dmamux_channel_type *RX_DMA_CHANNEL_MUX, dmamux_requst_id_sel_type RX_DMAMUX_DMAREQ_ID, IRQn_Type RX_DMA_Channel_IRQ, uint32_t RX_DMA_FDT_FLAG, uint8_t *DMA_BUF, uint16_t DMA_BUF_LEN, dma_channel_type *TX_DMA_CHANNEL, dmamux_channel_type *TX_DMA_CHANNEL_MUX, dmamux_requst_id_sel_type TX_DMAMUX_DMAREQ_ID, IRQn_Type TX_DMA_Channel_IRQ, uint32_t TX_DMA_FDT_FLAG, bool swap, usart_hardware_flow_control_type flow_control_type, uint32_t BoundRate, IRQn_Type irq, crm_periph_clock_type uartClock, uint8_t irqPriority, uint32_t rxBufferLength, uint32_t rxSnifferLength ) { /*включаем тактирование uart и нужных DMA */{ crm_periph_clock_enable(uartClock, TRUE); if (DMA_RX == DMA1 || DMA_TX == DMA1) { crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); } if (DMA_RX == DMA2 || DMA_TX == DMA2) { crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE); } } /*заполняем параметры и создаем все очереди до начала работы порта (иначе при раннем сробатывании прервывания все упадет)*/{ env->txAccessQueue = osMessageQueueNew(1, 1, NULL); env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL); if (rxSnifferLength) { env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL); } else { env->rxDataSnifferQueue = 0; } env->rxDmaFdtFlag = RX_DMA_FDT_FLAG; env->txDmaFdtFlag = TX_DMA_FDT_FLAG; env->txDmaChannel = TX_DMA_CHANNEL; env->rxDmaChannel = RX_DMA_CHANNEL; env->rxDmaBuf = DMA_BUF; env->rxDmaOffset = 0; } /*инициализируем uart */{ env->uart = uart; usart_reset(uart); usart_init(uart, BoundRate, USART_DATA_8BITS, USART_STOP_1_BIT); usart_hardware_flow_control_set(uart, flow_control_type); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); usart_dma_receiver_enable(uart, TRUE); usart_dma_transmitter_enable(uart, TRUE); if (swap) { usart_transmit_receive_pin_swap(uart, TRUE); } } /*инициализируем RX DMA в циклическом режиме*/if (DMA_RX) { dmamux_enable(DMA_RX, TRUE); // dma channel for usart rx configuration dma_reset(RX_DMA_CHANNEL); dma_default_para_init(&env->dma_rx_init_struct); env->dma_rx_init_struct.buffer_size = DMA_BUF_LEN; env->dma_rx_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; env->dma_rx_init_struct.memory_base_addr = (uint32_t) DMA_BUF; env->dma_rx_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; env->dma_rx_init_struct.memory_inc_enable = TRUE; env->dma_rx_init_struct.peripheral_base_addr = (uint32_t) &uart->dt; env->dma_rx_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; env->dma_rx_init_struct.peripheral_inc_enable = FALSE; env->dma_rx_init_struct.priority = DMA_PRIORITY_HIGH; env->dma_rx_init_struct.loop_mode_enable = TRUE; dma_init(RX_DMA_CHANNEL, &env->dma_rx_init_struct); // config flexible dma for usart7 rx dmamux_init(RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID); } /*инициализируем TX DMA*/if (DMA_TX) { dmamux_enable(DMA_TX, TRUE); // dma channel for usart tx configuration dma_reset(TX_DMA_CHANNEL); dma_default_para_init(&env->dma_tx_init_struct); env->dma_tx_init_struct.buffer_size = 0; env->dma_tx_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; env->dma_tx_init_struct.memory_base_addr = 0; env->dma_tx_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; env->dma_tx_init_struct.memory_inc_enable = TRUE; env->dma_tx_init_struct.peripheral_base_addr = (uint32_t) &uart->dt; env->dma_tx_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; env->dma_tx_init_struct.peripheral_inc_enable = FALSE; env->dma_tx_init_struct.priority = DMA_PRIORITY_HIGH; env->dma_tx_init_struct.loop_mode_enable = FALSE; dma_init(TX_DMA_CHANNEL, &env->dma_tx_init_struct); // config flexible dma for usart7 tx dmamux_init(TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID); } /*включаем rx dma и прерывания на нем*/if (DMA_RX) { dma_interrupt_enable(RX_DMA_CHANNEL, DMA_FDT_INT, TRUE); NVIC_EnableIRQ(RX_DMA_Channel_IRQ); NVIC_SetPriority(RX_DMA_Channel_IRQ, irqPriority); dma_channel_enable(RX_DMA_CHANNEL, TRUE); // uart7 rx begin dma receiving } /*включаем прерывания на tx dma*/if (DMA_TX) { dma_interrupt_enable(TX_DMA_CHANNEL, DMA_FDT_INT, TRUE); NVIC_EnableIRQ(TX_DMA_Channel_IRQ); NVIC_SetPriority(TX_DMA_Channel_IRQ, irqPriority); } /*включаем uart и прерывания на нем*/{ usart_interrupt_enable(uart, USART_IDLE_INT, TRUE); // usart_interrupt_enable(uart, USART_RDBF_INT, FALSE); NVIC_EnableIRQ(irq); NVIC_SetPriority(irq, irqPriority); usart_enable(uart, TRUE); } } void vSerialPortSendDMA( tSerialPortArtery *env, usart_type *uart, dma_type *DMA, dma_channel_type *DMA_CHANNEL, dmamux_channel_type *DMA_CHANNEL_MUX, dmamux_requst_id_sel_type DMAMUX_DMAREQ_ID, uint8_t *DMA_BUF, uint16_t DMA_BUF_LEN ) { dma_channel_enable(DMA_CHANNEL, FALSE); // dma channel for usart tx configuration dma_reset(DMA_CHANNEL); dma_default_para_init(&env->dma_tx_init_struct); env->dma_tx_init_struct.buffer_size = DMA_BUF_LEN; env->dma_tx_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; env->dma_tx_init_struct.memory_base_addr = (uint32_t) DMA_BUF; env->dma_tx_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; env->dma_tx_init_struct.memory_inc_enable = TRUE; env->dma_tx_init_struct.peripheral_base_addr = (uint32_t) &uart->dt; env->dma_tx_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; env->dma_tx_init_struct.peripheral_inc_enable = FALSE; env->dma_tx_init_struct.priority = DMA_PRIORITY_MEDIUM; env->dma_tx_init_struct.loop_mode_enable = FALSE; dma_init(DMA_CHANNEL, &env->dma_tx_init_struct); // config flexible dma for usart7 tx dmamux_init(DMA_CHANNEL_MUX, DMAMUX_DMAREQ_ID); dma_channel_enable(DMA_CHANNEL, TRUE); } /* void vSerialPortIrqProcessingDMA(tSerialPortArtery *env) { dma_channel_enable(env->dma_channel, FALSE); uint32_t len = env->dma_init_struct.buffer_size - env->dma_channel->dtcnt; env->offset = len; for (uint32_t i = 0; i < len; ++i) { osMessageQueuePut(env->rxDataQueue, &env->dma_buf[i], 0x0, 0U); if (env->rxDataSnifferQueue) { osMessageQueuePut(env->rxDataSnifferQueue, &env->dma_buf[i], 0x0, 0U); } } dma_init(env->dma_channel, &env->dma_init_struct); dma_channel_enable(env->dma_channel, TRUE); } */ void SerialPortFilter_RxDmaBufToQueue(tSerialPortArtery *env, uint32_t bufEnd, tSerialPortIO *virtualPort, uint16_t *counterBufFilterStr, uint8_t *bufStrFilter, uint16_t maxBufStrFilter, const char *FilterStr[], uint8_t countFiler) { for (uint32_t i = env->rxDmaOffset; i < bufEnd; ++i) { osMessageQueuePut(env->rxDataQueue, &env->rxDmaBuf[i], 0x0, 0U); if (env->rxDataSnifferQueue) { if (*counterBufFilterStr < maxBufStrFilter) { bufStrFilter[*counterBufFilterStr] = env->rxDmaBuf[i]; ++*counterBufFilterStr; } else { *counterBufFilterStr = 0; } bool isFilterFind = false; if (env->rxDmaBuf[i] == '\n') { for (uint8_t j = 0; j < countFiler; ++j) { if (memcmp(bufStrFilter, FilterStr[j], strlen(FilterStr[j])) == 0) { SerialPortTransmit(virtualPort, bufStrFilter, *counterBufFilterStr, 0); isFilterFind = true; break; } } if (isFilterFind == false) { for (uint16_t j = 0; j < *counterBufFilterStr; ++j) osMessageQueuePut(env->rxDataSnifferQueue, &bufStrFilter[j], 0x0, 0U); } *counterBufFilterStr = 0; memset(bufStrFilter, 0, maxBufStrFilter); } } } } void SerialPort_RxDmaBufToQueue(tSerialPortArtery *env, uint32_t bufEnd) { osStatus_t res; for (uint32_t i = env->rxDmaOffset; i < bufEnd; ++i) { osMessageQueuePut(env->rxDataQueue, &env->rxDmaBuf[i], 0x0, 0U); if (env->rxDataSnifferQueue) { osMessageQueuePut(env->rxDataSnifferQueue, &env->rxDmaBuf[i], 0x0, 0U); } } } void SerialPort_IrqProcessing_UartIdle(tSerialPortArtery *env) { // Смотрим idle прерывание if (usart_flag_get(env->uart, USART_IDLEF_FLAG)) { // Сброс прерывания usart_data_receive(env->uart); usart_flag_clear(env->uart, USART_IDLEF_FLAG); size_t bufEnd = env->dma_rx_init_struct.buffer_size - env->rxDmaChannel->dtcnt; SerialPort_RxDmaBufToQueue(env, bufEnd); env->rxDmaOffset = bufEnd; } } void SerialPort_IrqProcessing_DmaRxLoop(tSerialPortArtery *env) { if (dma_flag_get(env->rxDmaFdtFlag)) { SerialPort_RxDmaBufToQueue(env, env->dma_rx_init_struct.buffer_size); env->rxDmaOffset = 0; dma_flag_clear(env->rxDmaFdtFlag); } } void SerialPort_IrqProcessingFilter_UartIdle(tSerialPortArtery *env, tSerialPortIO *virtualPort, uint16_t *counterBufFilterStr, uint8_t *bufStrFilter, uint16_t maxBufStrFilter, const char *FilterStr[], uint8_t countFiler) { // Смотрим idle прерывание if (usart_flag_get(env->uart, USART_IDLEF_FLAG)) { // Сброс прерывания usart_data_receive(env->uart); usart_flag_clear(env->uart, USART_IDLEF_FLAG); size_t bufEnd = env->dma_rx_init_struct.buffer_size - env->rxDmaChannel->dtcnt; SerialPortFilter_RxDmaBufToQueue(env, bufEnd, virtualPort, counterBufFilterStr, bufStrFilter, maxBufStrFilter, FilterStr, countFiler); env->rxDmaOffset = bufEnd; } } void SerialPort_IrqProcessingFilter_DmaRxLoop(tSerialPortArtery *env, tSerialPortIO *virtualPort, uint16_t *counterBufFilterStr, uint8_t *bufStrFilter, uint16_t maxBufStrFilter, const char *FilterStr[], uint8_t countFiler) { if (dma_flag_get(env->rxDmaFdtFlag)) { SerialPortFilter_RxDmaBufToQueue(env, env->dma_rx_init_struct.buffer_size, virtualPort, counterBufFilterStr, bufStrFilter, maxBufStrFilter, FilterStr, countFiler); env->rxDmaOffset = 0; dma_flag_clear(env->rxDmaFdtFlag); } } static const uint8_t DUMMY_BYTE = 0xFF; void SerialPort_IrqProcessing_DmaTx(tSerialPortArtery *env) { if (dma_flag_get(env->txDmaFdtFlag)) { dma_flag_clear(env->txDmaFdtFlag); osMessageQueuePut(env->txAccessQueue, &DUMMY_BYTE, 0, 0); } } void SerialPort_IrqProcessing_DmaTxBlind(tSerialPortArtery *env) { if (dma_flag_get(env->txDmaFdtFlag)) { dma_flag_clear(env->txDmaFdtFlag); // osMessageQueuePut(env->txAccessQueue, &DUMMY_BYTE, 0, 0); } } void vSerialPortIrqProcessing(tSerialPortArtery *env) { uint8_t data; while (usart_flag_get(env->uart, USART_RDBF_FLAG)) { data = usart_data_receive(env->uart); osMessageQueuePut(env->rxDataQueue, &data, 0x0, 0U); if (env->rxDataSnifferQueue) { osMessageQueuePut(env->rxDataSnifferQueue, &data, 0x0, 0U); } } } static uint16_t vSerialPortReceiveQueue(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout, osMessageQueueId_t queueId) { uint16_t received = 0; if (timeout) { uint32_t endMs = SystemGetMs() + timeout; uint32_t leftMs; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { leftMs = endMs - SystemGetMs(); if (osMessageQueueGet(queueId, data, NULL, leftMs) == osOK) { --size; ++received; ++data; } } } else { while (size) { if (osMessageQueueGet(queueId, data, NULL, 0) == osOK) { --size; ++received; ++data; } else { return received; } } } return received; } static uint16_t vSerialPortReceive(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataQueue); } static uint16_t vSerialPortReceiveSniffer(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return env->rxDataSnifferQueue ? vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue) : 0; } static uint16_t vSerialPortReceiveSnifferSecond(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return env->rxDataSnifferSecondQueue ? vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataSnifferSecondQueue) : 0; } static uint16_t vSerialPortTransmitOverDma(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; dma_channel_enable(env->txDmaChannel, FALSE); env->dma_tx_init_struct.buffer_size = size; env->dma_tx_init_struct.memory_base_addr = (uint32_t) data; dma_init(env->txDmaChannel, &env->dma_tx_init_struct); dma_channel_enable(env->txDmaChannel, TRUE); uint8_t res; sent = (osMessageQueueGet(env->txAccessQueue, &res, 0, timeout) == osOK) ? size : 0; // SystemDelayMs(10); // // while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) { // if (dma_flag_get(env->txDmaFdtFlag) != RESET) // break; // SystemDelayMs(5); // } while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) { if (usart_flag_get(env->uart, USART_TDC_FLAG)) break; } dma_channel_enable(env->txDmaChannel, FALSE); // sent = size; return sent; } static uint16_t vSerialPortTransmitOverCore(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { if (usart_flag_get(env->uart, USART_TDBE_FLAG)) { usart_data_transmit(env->uart, *data); --size; ++data; ++sent; } } while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) { if (usart_flag_get(env->uart, USART_TDC_FLAG)) break; } return sent; } uint16_t vSerialPortBlindTransmit(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) { if (usart_flag_get(env->uart, USART_TDC_FLAG)) break; else { asm("nop"); } } // dma_channel_enable(env->txDmaChannel, FALSE); dma_channel_enable(env->txDmaChannel, FALSE); env->dma_tx_init_struct.buffer_size = size; env->dma_tx_init_struct.memory_base_addr = (uint32_t) data; dma_init(env->txDmaChannel, &env->dma_tx_init_struct); dma_channel_enable(env->txDmaChannel, TRUE); // uint8_t res; // int32_t s = SystemGetMs(); // sent = (osMessageQueueGet(env->txAccessQueue, &res, 0, timeout) == osOK) ? size : 0; // int32_t s1 = SystemGetMs(); // int32_t s3 = s1 - s; return sent; } static uint8_t LIN_DrvMakeCheckSum(uint8_t *pBuf, uint8_t u8Size, uint8_t u8Pid) { uint16_t u16Checksum = 0U; uint8_t u8Length = 0U; // For PID is 0x3C (ID 0x3C) or 0x7D (ID 0x3D) or 0xFE (ID 0x3E) or 0xBF (ID 0x3F) if ((0x3CU == u8Pid) || (0x7DU == u8Pid) || (0xFEU == u8Pid) || (0xBFU == u8Pid)) { u8Pid = 0U; } u16Checksum += u8Pid; for (u8Length = 0U; u8Length < u8Size; u8Length++) { u16Checksum += *pBuf; pBuf++; if (u16Checksum > 0xFFU) { u16Checksum -= 0xFFU; } } return ~(uint8_t)(u16Checksum); } static uint8_t LIN_CalcParity(uint8_t id) { uint8_t p0 = 0; uint8_t p1 = 0; // P0 = ID0 ^ ID1 ^ ID2 ^ ID4 p0 = ((id >> 0) & 0x01) ^ ((id >> 1) & 0x01) ^ ((id >> 2) & 0x01) ^ ((id >> 4) & 0x01); // P1 = ^(ID1 ^ ID3 ^ ID4 ^ ID5) p1 = 1 ^ ((id >> 1) & 0x01) ^ ((id >> 3) & 0x01) ^ ((id >> 4) & 0x01) ^ ((id >> 5) & 0x01); return (p1 << 7) | (p0 << 6); } // Измененный обработчик прерываний (без IDLE): void SerialPort_IrqProcessing_UartLin(tSerialPortArtery *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)) { if (env->linFrameStarted && (env->linByteCount < sizeof(env->linBuffer))) { uint8_t data = usart_data_receive(env->uart); env->linBuffer[env->linByteCount] = data; env->linByteCount++; env->linLastByteTime = SystemGetMs(); // Обновляем время } else { usart_data_receive(env->uart); 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(tSerialPortArtery *env) { // Проверка sync field if (env->linBuffer[0] != 0x55) { env->rxFrame.event = LIN_SYNC_ERROR; osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); return; } // Проверка PID uint8_t receivedPid = env->linBuffer[1]; uint8_t id = receivedPid & 0x3F; uint8_t expectedPid = id | LIN_CalcParity(id); if (receivedPid != expectedPid) { env->rxFrame.event = LIN_PID_ERROR; osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); return; } env->rxFrame.id = id; env->rxFrame.dataLen = env->linByteCount - 3; if (env->rxFrame.dataLen > 8) { env->rxFrame.event = LIN_FRAME_ERROR; osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); return; } // Копируем данные for (uint8_t i = 0; i < env->rxFrame.dataLen; i++) { env->rxFrame.data[i] = env->linBuffer[2 + i]; } // Проверка checksum env->rxFrame.checksum = env->linBuffer[env->linByteCount - 1]; uint8_t calculatedChecksum = LIN_DrvMakeCheckSum( env->rxFrame.data, env->rxFrame.dataLen, receivedPid ); if (env->rxFrame.checksum != calculatedChecksum) { env->rxFrame.event = LIN_CHECKSUM_ERROR; } else { env->rxFrame.event = LIN_RX_COMPLETED; } osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); } // Функция проверки таймаута (вызывать из таймера, например, каждые 1-5 мс) void LIN_CheckTimeout(tSerialPortArtery *env) { if (!env->linFrameStarted) { return; } uint32_t now = SystemGetMs(); uint32_t elapsed = now - env->linLastByteTime; if (elapsed >= env->linFrameTimeoutMs) { // Таймаут - кадр должен быть завершен if (env->linByteCount >= 3) { // Пытаемся обработать полученные данные LIN_ProcessReceivedFrame(env); } else { // Недостаточно данных env->rxFrame.event = LIN_TIMEOUT; osMessageQueuePut(env->rxDataQueue, &env->rxFrame, 0, 0); } env->linFrameStarted = false; } } bool vSerialPortSendLinFrame(tSerialPortArtery *env, const lin_frame_t *pFrame, uint32_t timeout) { uint8_t txBuffer[11]; // Максимальный размер LIN кадра (без break) uint8_t idx = 0; if ((!env) || (!pFrame)) { return false; } // Проверка валидности данных if (pFrame->dataLen > 8) { return false; } // 1. Формирование LIN кадра // Sync field txBuffer[idx++] = 0x55; // PID (ID + parity) uint8_t pid = pFrame->id | LIN_CalcParity(pFrame->id); txBuffer[idx++] = pid; // Data bytes for (uint8_t i = 0; i < pFrame->dataLen; i++) { txBuffer[idx++] = pFrame->data[i]; } // Checksum txBuffer[idx++] = pFrame->checksum; // 2. Отправка break field usart_break_send(env->uart); // Ожидание завершения отправки break uint32_t breakTimeout = SystemGetMs() + 10; // 10мс максимум на break while (usart_flag_get(env->uart, USART_TDBE_FLAG) == RESET) { if (SystemGetMs() > breakTimeout) { return false; } } // 3. Отправка данных (возвращает количество отправленных байт) uint16_t sent = vSerialPortTransmitOverCore(env, txBuffer, idx, timeout); return (sent == idx); // Успех, если все байты отправлены } static SerialPortIOTransaction vSerialPortTransmitterGet(tSerialPortArtery *env) { #ifdef UART_DMA_SEND if (env->txDmaChannel) return (SerialPortIOTransaction) vSerialPortTransmitOverDma; else return (SerialPortIOTransaction) vSerialPortTransmitOverCore; #else return (SerialPortIOTransaction) vSerialPortTransmitOverCore; #endif } tSerialPortIO vSerialPortGetIo(tSerialPortArtery *env) { tSerialPortIO io = { .env = env, .receive = (SerialPortIOTransaction) vSerialPortReceive, .transmit = vSerialPortTransmitterGet(env) }; return io; } tSerialPortIO vSerialPortGetSnifferIo(tSerialPortArtery *env) { tSerialPortIO io = { .env = env, .receive = (SerialPortIOTransaction) vSerialPortReceiveSniffer, .transmit = vSerialPortTransmitterGet(env) }; return io; } tSerialPortIO SerialPort_GetSnifferSecondIo(tSerialPortArtery *env) { tSerialPortIO io = { .env = env, .receive = (SerialPortIOTransaction) vSerialPortReceiveSnifferSecond, .transmit = vSerialPortTransmitterGet(env) }; return io; }