SerialPort_ARTERY_AT32/Src/SerialPortArtery.c

801 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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;
}