Начало

This commit is contained in:
cfif 2025-09-23 17:12:43 +03:00
commit c72b2179f5
3 changed files with 1036 additions and 0 deletions

213
Inc/SerialPortArtery.h Normal file
View File

@ -0,0 +1,213 @@
//
// Created by cfif on 16.09.22.
//
#ifndef SERIALPORT_SERIALPORT_ARTERY_H
#define SERIALPORT_SERIALPORT_ARTERY_H
#include "SerialPort.h"
#include "at32f435_437.h"
#include "cmsis_os2.h"
#include "stdbool.h"
typedef struct {
usart_type *uart;
dma_channel_type *rxDmaChannel;
dma_init_type dma_rx_init_struct;
dma_init_type dma_tx_init_struct;
uint32_t rxDmaFdtFlag;//full data transmit flag
uint32_t txDmaFdtFlag;//full data transmit flag
dma_channel_type *txDmaChannel;
uint8_t *rxDmaBuf;
uint32_t rxDmaOffset;
// osMutexId_t dmaAccess;
osMessageQueueId_t txAccessQueue;
osMessageQueueId_t rxDataQueue;
osMessageQueueId_t rxDataSnifferQueue;
osMessageQueueId_t rxDataSnifferSecondQueue;
} tSerialPortArtery;
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
);
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
);
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
);
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
);
#define vSerialPortInitDMAName(ENV, NAME, DMA, RX_DMA_CHANNEL, RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID, RX_DMA_Channel_IRQ, RX_DMA_FDT_FLAG, DMA_BUF, DMA_BUF_LEN, TX_DMA_CHANNEL, TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID, TX_DMA_Channel_IRQ, TX_DMA_FDT_FLAG, SWAP, BOUND_RATE, PRIORITY, LEN) \
vSerialPortInitDMA(ENV, NAME, DMA, RX_DMA_CHANNEL, RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID, RX_DMA_Channel_IRQ, RX_DMA_FDT_FLAG, DMA_BUF, DMA_BUF_LEN, TX_DMA_CHANNEL, TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID, TX_DMA_Channel_IRQ, TX_DMA_FDT_FLAG, SWAP, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, 0)
#define vSerialPortInitDMANameWithSniffer(ENV, NAME, DMA, RX_DMA_CHANNEL, RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID, RX_DMA_Channel_IRQ, RX_DMA_FDT_FLAG, DMA_BUF, DMA_BUF_LEN, TX_DMA_CHANNEL, TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID, TX_DMA_Channel_IRQ, TX_DMA_FDT_FLAG, SWAP, BOUND_RATE, PRIORITY, LEN, SNIFFER_LEN) \
vSerialPortInitDMA(ENV, NAME, DMA, RX_DMA_CHANNEL, RX_DMA_CHANNEL_MUX, RX_DMAMUX_DMAREQ_ID, RX_DMA_Channel_IRQ, RX_DMA_FDT_FLAG, DMA_BUF, DMA_BUF_LEN, TX_DMA_CHANNEL, TX_DMA_CHANNEL_MUX, TX_DMAMUX_DMAREQ_ID, TX_DMA_Channel_IRQ, TX_DMA_FDT_FLAG, SWAP, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, SNIFFER_LEN)
#define DMANONE_CHANNELNONE NULL
#define DMANONE NULL
#define DMANONEMUX_CHANNELNONE NULL
#define DMANONE_FDTNONE_FLAG (uint32_t)0
#define DMANONE_ChannelNONE_IRQn (IRQn_Type)0
#define vSerialPortInitDmaWithNameAndSniffer(\
ENV, NAME, BOUND_RATE, \
RX_DMA, RX_CH, \
TX_DMA, TX_CH, \
SWAP, PRIORITY, \
RX_DMA_BUF, RX_DMA_BUF_LEN, \
QUEUE_LEN, SNIFFER_LEN \
) \
vSerialPortInitDMA(\
ENV, NAME, DMA##RX_DMA, DMA##TX_DMA, \
DMA##RX_DMA##_CHANNEL##RX_CH, DMA##RX_DMA##MUX_CHANNEL##RX_CH, DMAMUX_DMAREQ_ID_##NAME##_RX, DMA##RX_DMA##_Channel##RX_CH##_IRQn, DMA##RX_DMA##_FDT##RX_CH##_FLAG,\
RX_DMA_BUF, RX_DMA_BUF_LEN, \
DMA##TX_DMA##_CHANNEL##TX_CH, DMA##TX_DMA##MUX_CHANNEL##TX_CH, DMAMUX_DMAREQ_ID_##NAME##_TX, DMA##TX_DMA##_Channel##TX_CH##_IRQn, DMA##TX_DMA##_FDT##TX_CH##_FLAG,\
SWAP, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, \
PRIORITY, QUEUE_LEN, SNIFFER_LEN\
)
#define vSerialPortInitDmaExtWithNameAndSniffer(\
ENV, NAME, BOUND_RATE, \
RX_DMA, RX_CH, \
TX_DMA, TX_CH, \
SWAP, FLOW, PRIORITY, \
RX_DMA_BUF, RX_DMA_BUF_LEN, \
QUEUE_LEN, SNIFFER_LEN \
) \
vSerialPortInitDMAExt(\
ENV, NAME, DMA##RX_DMA, DMA##TX_DMA, \
DMA##RX_DMA##_CHANNEL##RX_CH, DMA##RX_DMA##MUX_CHANNEL##RX_CH, DMAMUX_DMAREQ_ID_##NAME##_RX, DMA##RX_DMA##_Channel##RX_CH##_IRQn, DMA##RX_DMA##_FDT##RX_CH##_FLAG,\
RX_DMA_BUF, RX_DMA_BUF_LEN, \
DMA##TX_DMA##_CHANNEL##TX_CH, DMA##TX_DMA##MUX_CHANNEL##TX_CH, DMAMUX_DMAREQ_ID_##NAME##_TX, DMA##TX_DMA##_Channel##TX_CH##_IRQn, DMA##TX_DMA##_FDT##TX_CH##_FLAG,\
SWAP, FLOW, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, \
PRIORITY, QUEUE_LEN, SNIFFER_LEN\
)
#define vSerialPortInitName(ENV, NAME, SWAP, BOUND_RATE, PRIORITY, LEN) \
vSerialPortInit(ENV, NAME, SWAP, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, 0)
#define vSerialPortExtInitName(ENV, NAME, SWAP, FLOW, BOUND_RATE, PRIORITY, LEN) \
vSerialPortInit(ENV, NAME, SWAP, FLOW, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, 0)
#define vSerialPortInitNameWithSniffer(ENV, NAME, SWAP, BOUND_RATE, PRIORITY, LEN, SNIFFER_LEN) \
vSerialPortInit(ENV, NAME, SWAP, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, SNIFFER_LEN)
#define vSerialPortExtInitNameWithSniffer(ENV, NAME, SWAP, FLOW, BOUND_RATE, PRIORITY, LEN, SNIFFER_LEN) \
vSerialPortInit(ENV, NAME, SWAP, FLOW, BOUND_RATE, NAME##_IRQn, CRM_##NAME##_PERIPH_CLOCK, PRIORITY, LEN, SNIFFER_LEN)
void vSerialPortIrqProcessing(tSerialPortArtery *env);
void vSerialPortIrqProcessingDMA(tSerialPortArtery *env);
//void vSerialPortIrqProcessingDMAloop(tSerialPortArtery *env, uint32_t len);
void SerialPort_IrqProcessing_UartIdle(tSerialPortArtery *env);
void SerialPort_IrqProcessing_DmaRxLoop(tSerialPortArtery *env);
void SerialPort_IrqProcessingFilter_UartIdle(tSerialPortArtery *env, tSerialPortIO *virtualPort, uint16_t *counterBufFilterStr, uint8_t *bufStrFilter, uint16_t maxBufStrFilter, const char *FilterStr[], uint8_t countFiler);
void SerialPort_IrqProcessingFilter_DmaRxLoop(tSerialPortArtery *env, tSerialPortIO *virtualPort, uint16_t *counterBufFilterStr, uint8_t *bufStrFilter, uint16_t maxBufStrFilter, const char *FilterStr[], uint8_t countFiler);
void SerialPort_IrqProcessing_DmaTx(tSerialPortArtery *env);
tSerialPortIO vSerialPortGetIo(tSerialPortArtery *env);
tSerialPortIO vSerialPortGetSnifferIo(tSerialPortArtery *env);
tSerialPortIO SerialPort_GetSnifferSecondIo(tSerialPortArtery *env);
uint16_t vSerialPortTransmit(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout);
uint16_t vSerialPortBlindTransmit(tSerialPortArtery *env, uint8_t *data, uint16_t size, uint32_t timeout);
void SerialPort_IrqProcessing_DmaTxBlind(tSerialPortArtery *env);
#endif //SERIALPORT_SERIALPORT_ARTERY_H

801
Src/SerialPortArtery.c Normal file
View File

@ -0,0 +1,801 @@
//
// Created by cfif on 16.09.22.
//
#include <SystemDelayInterface.h>
#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 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 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;
}

22
modular.json Normal file
View File

@ -0,0 +1,22 @@
{
"dep": [
{
"type": "git",
"provider": "HVAC_DEV",
"repo": "SerialPort"
},
{
"type": "git",
"provider": "HVAC_DEV",
"repo": "SystemDelayInterface"
}
],
"cmake": {
"inc_dirs": [
"Inc"
],
"srcs": [
"Src/**.c"
]
}
}