mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 16:25:31 +03:00
commit
5fc78a43fc
8 changed files with 176 additions and 460 deletions
|
@ -67,7 +67,7 @@ MCU_COMMON_SRC = \
|
||||||
drivers/dma.c \
|
drivers/dma.c \
|
||||||
drivers/inverter.c \
|
drivers/inverter.c \
|
||||||
drivers/light_ws2811strip_stdperiph.c \
|
drivers/light_ws2811strip_stdperiph.c \
|
||||||
drivers/serial_uart_init.c \
|
drivers/serial_uart_stdperiph.c \
|
||||||
drivers/serial_uart_stm32f10x.c \
|
drivers/serial_uart_stm32f10x.c \
|
||||||
drivers/system_stm32f10x.c \
|
drivers/system_stm32f10x.c \
|
||||||
drivers/timer_stm32f10x.c
|
drivers/timer_stm32f10x.c
|
||||||
|
|
|
@ -86,7 +86,7 @@ MCU_COMMON_SRC = \
|
||||||
drivers/transponder_ir_io_stdperiph.c \
|
drivers/transponder_ir_io_stdperiph.c \
|
||||||
drivers/pwm_output_dshot.c \
|
drivers/pwm_output_dshot.c \
|
||||||
drivers/pwm_output_dshot_shared.c \
|
drivers/pwm_output_dshot_shared.c \
|
||||||
drivers/serial_uart_init.c \
|
drivers/serial_uart_stdperiph.c \
|
||||||
drivers/serial_uart_stm32f30x.c \
|
drivers/serial_uart_stm32f30x.c \
|
||||||
drivers/system_stm32f30x.c \
|
drivers/system_stm32f30x.c \
|
||||||
drivers/timer_stm32f30x.c
|
drivers/timer_stm32f30x.c
|
||||||
|
|
|
@ -180,7 +180,7 @@ MCU_COMMON_SRC = \
|
||||||
drivers/transponder_ir_io_stdperiph.c \
|
drivers/transponder_ir_io_stdperiph.c \
|
||||||
drivers/pwm_output_dshot.c \
|
drivers/pwm_output_dshot.c \
|
||||||
drivers/pwm_output_dshot_shared.c \
|
drivers/pwm_output_dshot_shared.c \
|
||||||
drivers/serial_uart_init.c \
|
drivers/serial_uart_stdperiph.c \
|
||||||
drivers/serial_uart_stm32f4xx.c \
|
drivers/serial_uart_stm32f4xx.c \
|
||||||
drivers/system_stm32f4xx.c \
|
drivers/system_stm32f4xx.c \
|
||||||
drivers/timer_stm32f4xx.c \
|
drivers/timer_stm32f4xx.c \
|
||||||
|
|
|
@ -179,13 +179,12 @@ MCU_COMMON_SRC = \
|
||||||
drivers/timer_hal.c \
|
drivers/timer_hal.c \
|
||||||
drivers/timer_stm32f7xx.c \
|
drivers/timer_stm32f7xx.c \
|
||||||
drivers/system_stm32f7xx.c \
|
drivers/system_stm32f7xx.c \
|
||||||
drivers/serial_uart_stm32f7xx.c \
|
drivers/serial_uart_hal.c \
|
||||||
drivers/serial_uart_hal.c
|
drivers/serial_uart_stm32f7xx.c
|
||||||
|
|
||||||
MCU_EXCLUDES = \
|
MCU_EXCLUDES = \
|
||||||
drivers/bus_i2c.c \
|
drivers/bus_i2c.c \
|
||||||
drivers/timer.c \
|
drivers/timer.c
|
||||||
drivers/serial_uart.c
|
|
||||||
|
|
||||||
MSC_SRC = \
|
MSC_SRC = \
|
||||||
drivers/usb_msc_f7xx.c \
|
drivers/usb_msc_f7xx.c \
|
||||||
|
|
|
@ -235,8 +235,8 @@ MCU_COMMON_SRC = \
|
||||||
drivers/system_stm32h7xx.c \
|
drivers/system_stm32h7xx.c \
|
||||||
drivers/timer_hal.c \
|
drivers/timer_hal.c \
|
||||||
drivers/timer_stm32h7xx.c \
|
drivers/timer_stm32h7xx.c \
|
||||||
drivers/serial_uart_stm32h7xx.c \
|
|
||||||
drivers/serial_uart_hal.c \
|
drivers/serial_uart_hal.c \
|
||||||
|
drivers/serial_uart_stm32h7xx.c \
|
||||||
drivers/bus_quadspi_hal.c \
|
drivers/bus_quadspi_hal.c \
|
||||||
drivers/bus_spi_hal.c \
|
drivers/bus_spi_hal.c \
|
||||||
drivers/dma_stm32h7xx.c \
|
drivers/dma_stm32h7xx.c \
|
||||||
|
@ -253,8 +253,7 @@ MCU_COMMON_SRC = \
|
||||||
|
|
||||||
MCU_EXCLUDES = \
|
MCU_EXCLUDES = \
|
||||||
drivers/bus_i2c.c \
|
drivers/bus_i2c.c \
|
||||||
drivers/timer.c \
|
drivers/timer.c
|
||||||
drivers/serial_uart.c
|
|
||||||
|
|
||||||
#MSC_SRC = \
|
#MSC_SRC = \
|
||||||
# drivers/usb_msc_h7xx.c \
|
# drivers/usb_msc_h7xx.c \
|
||||||
|
|
|
@ -33,19 +33,42 @@
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART
|
||||||
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "build/atomic.h"
|
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
|
||||||
#include "drivers/dma.h"
|
#include "drivers/dma.h"
|
||||||
#include "drivers/inverter.h"
|
|
||||||
#include "drivers/nvic.h"
|
|
||||||
#include "drivers/rcc.h"
|
#include "drivers/rcc.h"
|
||||||
|
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/serial_uart.h"
|
#include "drivers/serial_uart.h"
|
||||||
#include "drivers/serial_uart_impl.h"
|
#include "drivers/serial_uart_impl.h"
|
||||||
|
|
||||||
|
serialPort_t *uartOpen(UARTDevice_e device, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
||||||
|
{
|
||||||
|
uartPort_t *s = serialUART(device, baudRate, mode, options);
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return (serialPort_t *)s;
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
|
s->txDMAEmpty = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// common serial initialisation code should move to serialPort::init()
|
||||||
|
s->port.rxBufferHead = s->port.rxBufferTail = 0;
|
||||||
|
s->port.txBufferHead = s->port.txBufferTail = 0;
|
||||||
|
// callback works for IRQ-based RX ONLY
|
||||||
|
s->port.rxCallback = rxCallback;
|
||||||
|
s->port.rxCallbackData = rxCallbackData;
|
||||||
|
s->port.mode = mode;
|
||||||
|
s->port.baudRate = baudRate;
|
||||||
|
s->port.options = options;
|
||||||
|
|
||||||
|
uartReconfigure(s);
|
||||||
|
|
||||||
|
return (serialPort_t *)s;
|
||||||
|
}
|
||||||
|
|
||||||
static void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
|
static void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
|
||||||
{
|
{
|
||||||
uartPort_t *uartPort = (uartPort_t *)instance;
|
uartPort_t *uartPort = (uartPort_t *)instance;
|
||||||
|
@ -60,66 +83,26 @@ static void uartSetMode(serialPort_t *instance, portMode_e mode)
|
||||||
uartReconfigure(uartPort);
|
uartReconfigure(uartPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uartTryStartTxDMA(uartPort_t *s)
|
|
||||||
{
|
|
||||||
// uartTryStartTxDMA must be protected, since it is called from
|
|
||||||
// uartWrite and handleUsartTxDma (an ISR).
|
|
||||||
|
|
||||||
ATOMIC_BLOCK(NVIC_PRIO_SERIALUART_TXDMA) {
|
|
||||||
if (IS_DMA_ENABLED(s->txDMAResource)) {
|
|
||||||
// DMA is already in progress
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For F4 (and F1), there are cases that NDTR (CNDTR for F1) is non-zero upon TC interrupt.
|
|
||||||
// We couldn't find out the root cause, so mask the case here.
|
|
||||||
// F3 is not confirmed to be vulnerable, but not excluded as a safety.
|
|
||||||
|
|
||||||
if (xDMA_GetCurrDataCounter(s->txDMAResource)) {
|
|
||||||
// Possible premature TC case.
|
|
||||||
goto reenable;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->port.txBufferHead == s->port.txBufferTail) {
|
|
||||||
// No more data to transmit.
|
|
||||||
s->txDMAEmpty = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a new transaction.
|
|
||||||
|
|
||||||
#ifdef STM32F4
|
|
||||||
xDMA_MemoryTargetConfig(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail], DMA_Memory_0);
|
|
||||||
#else
|
|
||||||
DMAx_SetMemoryAddress(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s->port.txBufferHead > s->port.txBufferTail) {
|
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferHead - s->port.txBufferTail);
|
|
||||||
s->port.txBufferTail = s->port.txBufferHead;
|
|
||||||
} else {
|
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferSize - s->port.txBufferTail);
|
|
||||||
s->port.txBufferTail = 0;
|
|
||||||
}
|
|
||||||
s->txDMAEmpty = false;
|
|
||||||
|
|
||||||
reenable:
|
|
||||||
xDMA_Cmd(s->txDMAResource, ENABLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance)
|
static uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance)
|
||||||
{
|
{
|
||||||
const uartPort_t *s = (const uartPort_t*)instance;
|
const uartPort_t *s = (const uartPort_t*)instance;
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
if (s->rxDMAResource) {
|
if (s->rxDMAResource) {
|
||||||
|
// XXX Could be consolidated
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
uint32_t rxDMAHead = __HAL_DMA_GET_COUNTER(s->Handle.hdmarx);
|
||||||
|
#else
|
||||||
uint32_t rxDMAHead = xDMA_GetCurrDataCounter(s->rxDMAResource);
|
uint32_t rxDMAHead = xDMA_GetCurrDataCounter(s->rxDMAResource);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (rxDMAHead >= s->rxDMAPos) {
|
if (rxDMAHead >= s->rxDMAPos) {
|
||||||
return rxDMAHead - s->rxDMAPos;
|
return rxDMAHead - s->rxDMAPos;
|
||||||
} else {
|
} else {
|
||||||
return s->port.rxBufferSize + rxDMAHead - s->rxDMAPos;
|
return s->port.rxBufferSize + rxDMAHead - s->rxDMAPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s->port.rxBufferHead >= s->port.rxBufferTail) {
|
if (s->port.rxBufferHead >= s->port.rxBufferTail) {
|
||||||
return s->port.rxBufferHead - s->port.rxBufferTail;
|
return s->port.rxBufferHead - s->port.rxBufferTail;
|
||||||
|
@ -140,12 +123,17 @@ static uint32_t uartTotalTxBytesFree(const serialPort_t *instance)
|
||||||
bytesUsed = s->port.txBufferSize + s->port.txBufferHead - s->port.txBufferTail;
|
bytesUsed = s->port.txBufferSize + s->port.txBufferHead - s->port.txBufferTail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
if (s->txDMAResource) {
|
if (s->txDMAResource) {
|
||||||
/*
|
/*
|
||||||
* When we queue up a DMA request, we advance the Tx buffer tail before the transfer finishes, so we must add
|
* When we queue up a DMA request, we advance the Tx buffer tail before the transfer finishes, so we must add
|
||||||
* the remaining size of that in-progress transfer here instead:
|
* the remaining size of that in-progress transfer here instead:
|
||||||
*/
|
*/
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
bytesUsed += __HAL_DMA_GET_COUNTER(s->Handle.hdmatx);
|
||||||
|
#else
|
||||||
bytesUsed += xDMA_GetCurrDataCounter(s->txDMAResource);
|
bytesUsed += xDMA_GetCurrDataCounter(s->txDMAResource);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the Tx buffer is being written to very quickly, we might have advanced the head into the buffer
|
* If the Tx buffer is being written to very quickly, we might have advanced the head into the buffer
|
||||||
|
@ -159,6 +147,7 @@ static uint32_t uartTotalTxBytesFree(const serialPort_t *instance)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return (s->port.txBufferSize - 1) - bytesUsed;
|
return (s->port.txBufferSize - 1) - bytesUsed;
|
||||||
}
|
}
|
||||||
|
@ -166,9 +155,12 @@ static uint32_t uartTotalTxBytesFree(const serialPort_t *instance)
|
||||||
static bool isUartTransmitBufferEmpty(const serialPort_t *instance)
|
static bool isUartTransmitBufferEmpty(const serialPort_t *instance)
|
||||||
{
|
{
|
||||||
const uartPort_t *s = (const uartPort_t *)instance;
|
const uartPort_t *s = (const uartPort_t *)instance;
|
||||||
|
#ifdef USE_DMA
|
||||||
if (s->txDMAResource) {
|
if (s->txDMAResource) {
|
||||||
return s->txDMAEmpty;
|
return s->txDMAEmpty;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
return s->port.txBufferTail == s->port.txBufferHead;
|
return s->port.txBufferTail == s->port.txBufferHead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,11 +170,14 @@ static uint8_t uartRead(serialPort_t *instance)
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
uartPort_t *s = (uartPort_t *)instance;
|
uartPort_t *s = (uartPort_t *)instance;
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
if (s->rxDMAResource) {
|
if (s->rxDMAResource) {
|
||||||
ch = s->port.rxBuffer[s->port.rxBufferSize - s->rxDMAPos];
|
ch = s->port.rxBuffer[s->port.rxBufferSize - s->rxDMAPos];
|
||||||
if (--s->rxDMAPos == 0)
|
if (--s->rxDMAPos == 0)
|
||||||
s->rxDMAPos = s->port.rxBufferSize;
|
s->rxDMAPos = s->port.rxBufferSize;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
ch = s->port.rxBuffer[s->port.rxBufferTail];
|
ch = s->port.rxBuffer[s->port.rxBufferTail];
|
||||||
if (s->port.rxBufferTail + 1 >= s->port.rxBufferSize) {
|
if (s->port.rxBufferTail + 1 >= s->port.rxBufferSize) {
|
||||||
s->port.rxBufferTail = 0;
|
s->port.rxBufferTail = 0;
|
||||||
|
@ -197,17 +192,26 @@ static uint8_t uartRead(serialPort_t *instance)
|
||||||
static void uartWrite(serialPort_t *instance, uint8_t ch)
|
static void uartWrite(serialPort_t *instance, uint8_t ch)
|
||||||
{
|
{
|
||||||
uartPort_t *s = (uartPort_t *)instance;
|
uartPort_t *s = (uartPort_t *)instance;
|
||||||
|
|
||||||
s->port.txBuffer[s->port.txBufferHead] = ch;
|
s->port.txBuffer[s->port.txBufferHead] = ch;
|
||||||
|
|
||||||
if (s->port.txBufferHead + 1 >= s->port.txBufferSize) {
|
if (s->port.txBufferHead + 1 >= s->port.txBufferSize) {
|
||||||
s->port.txBufferHead = 0;
|
s->port.txBufferHead = 0;
|
||||||
} else {
|
} else {
|
||||||
s->port.txBufferHead++;
|
s->port.txBufferHead++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DMA
|
||||||
if (s->txDMAResource) {
|
if (s->txDMAResource) {
|
||||||
uartTryStartTxDMA(s);
|
uartTryStartTxDMA(s);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
__HAL_UART_ENABLE_IT(&s->Handle, UART_IT_TXE);
|
||||||
|
#else
|
||||||
USART_ITConfig(s->USARTx, USART_IT_TXE, ENABLE);
|
USART_ITConfig(s->USARTx, USART_IT_TXE, ENABLE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,75 +232,43 @@ const struct serialPortVTable uartVTable[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define UART_IRQHandler(type, dev) \
|
||||||
|
void type ## dev ## _IRQHandler(void) \
|
||||||
|
{ \
|
||||||
|
uartPort_t *s = &(uartDevmap[UARTDEV_ ## dev]->port); \
|
||||||
|
uartIrqHandler(s); \
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_UART1
|
#ifdef USE_UART1
|
||||||
// USART1 Rx/Tx IRQ Handler
|
UART_IRQHandler(USART, 1) // USART1 Rx/Tx IRQ Handler
|
||||||
void USART1_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_1]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART2
|
#ifdef USE_UART2
|
||||||
// USART2 Rx/Tx IRQ Handler
|
UART_IRQHandler(USART, 2) // USART2 Rx/Tx IRQ Handler
|
||||||
void USART2_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_2]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART3
|
#ifdef USE_UART3
|
||||||
// USART3 Rx/Tx IRQ Handler
|
UART_IRQHandler(USART, 3) // USART3 Rx/Tx IRQ Handler
|
||||||
void USART3_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_3]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART4
|
#ifdef USE_UART4
|
||||||
// UART4 Rx/Tx IRQ Handler
|
UART_IRQHandler(UART, 4) // UART4 Rx/Tx IRQ Handler
|
||||||
void UART4_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_4]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART5
|
#ifdef USE_UART5
|
||||||
// UART5 Rx/Tx IRQ Handler
|
UART_IRQHandler(UART, 5) // UART5 Rx/Tx IRQ Handler
|
||||||
void UART5_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_5]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART6
|
#ifdef USE_UART6
|
||||||
// USART6 Rx/Tx IRQ Handler
|
UART_IRQHandler(USART, 6) // USART6 Rx/Tx IRQ Handler
|
||||||
void USART6_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_6]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART7
|
#ifdef USE_UART7
|
||||||
// UART7 Rx/Tx IRQ Handler
|
UART_IRQHandler(UART, 7) // UART7 Rx/Tx IRQ Handler
|
||||||
void UART7_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_7]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_UART8
|
#ifdef USE_UART8
|
||||||
// UART8 Rx/Tx IRQ Handler
|
UART_IRQHandler(UART, 8) // UART8 Rx/Tx IRQ Handler
|
||||||
void UART8_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_8]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // USE_UART
|
||||||
|
|
|
@ -68,19 +68,6 @@ static void usartConfigurePinInversion(uartPort_t *uartPort) {
|
||||||
|
|
||||||
void uartReconfigure(uartPort_t *uartPort)
|
void uartReconfigure(uartPort_t *uartPort)
|
||||||
{
|
{
|
||||||
/*RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
|
|
||||||
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_USART3|
|
|
||||||
RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_UART5|RCC_PERIPHCLK_USART6|RCC_PERIPHCLK_UART7|RCC_PERIPHCLK_UART8;
|
|
||||||
RCC_PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Uart4ClockSelection = RCC_UART4CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Uart5ClockSelection = RCC_UART5CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Usart6ClockSelection = RCC_USART6CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Uart7ClockSelection = RCC_UART7CLKSOURCE_SYSCLK;
|
|
||||||
RCC_PeriphClkInit.Uart8ClockSelection = RCC_UART8CLKSOURCE_SYSCLK;
|
|
||||||
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);*/
|
|
||||||
|
|
||||||
HAL_UART_DeInit(&uartPort->Handle);
|
HAL_UART_DeInit(&uartPort->Handle);
|
||||||
uartPort->Handle.Init.BaudRate = uartPort->port.baudRate;
|
uartPort->Handle.Init.BaudRate = uartPort->port.baudRate;
|
||||||
// according to the stm32 documentation wordlen has to be 9 for parity bits
|
// according to the stm32 documentation wordlen has to be 9 for parity bits
|
||||||
|
@ -208,47 +195,6 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPort_t *uartOpen(UARTDevice_e device, serialReceiveCallbackPtr callback, void *callbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartPort_t *s = serialUART(device, baudRate, mode, options);
|
|
||||||
|
|
||||||
if (!s) {
|
|
||||||
return (serialPort_t *)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
s->txDMAEmpty = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// common serial initialisation code should move to serialPort::init()
|
|
||||||
s->port.rxBufferHead = s->port.rxBufferTail = 0;
|
|
||||||
s->port.txBufferHead = s->port.txBufferTail = 0;
|
|
||||||
// callback works for IRQ-based RX ONLY
|
|
||||||
s->port.rxCallback = callback;
|
|
||||||
s->port.rxCallbackData = callbackData;
|
|
||||||
s->port.mode = mode;
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
s->port.options = options;
|
|
||||||
|
|
||||||
uartReconfigure(s);
|
|
||||||
|
|
||||||
return (serialPort_t *)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
|
|
||||||
{
|
|
||||||
uartPort_t *uartPort = (uartPort_t *)instance;
|
|
||||||
uartPort->port.baudRate = baudRate;
|
|
||||||
uartReconfigure(uartPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartSetMode(serialPort_t *instance, portMode_e mode)
|
|
||||||
{
|
|
||||||
uartPort_t *uartPort = (uartPort_t *)instance;
|
|
||||||
uartPort->port.mode = mode;
|
|
||||||
uartReconfigure(uartPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
#ifdef USE_DMA
|
||||||
void uartTryStartTxDMA(uartPort_t *s)
|
void uartTryStartTxDMA(uartPort_t *s)
|
||||||
{
|
{
|
||||||
|
@ -286,209 +232,4 @@ void uartTryStartTxDMA(uartPort_t *s)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance)
|
#endif // USE_UART
|
||||||
{
|
|
||||||
uartPort_t *s = (uartPort_t*)instance;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (s->rxDMAResource) {
|
|
||||||
uint32_t rxDMAHead = __HAL_DMA_GET_COUNTER(s->Handle.hdmarx);
|
|
||||||
|
|
||||||
if (rxDMAHead >= s->rxDMAPos) {
|
|
||||||
return rxDMAHead - s->rxDMAPos;
|
|
||||||
} else {
|
|
||||||
return s->port.rxBufferSize + rxDMAHead - s->rxDMAPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s->port.rxBufferHead >= s->port.rxBufferTail) {
|
|
||||||
return s->port.rxBufferHead - s->port.rxBufferTail;
|
|
||||||
} else {
|
|
||||||
return s->port.rxBufferSize + s->port.rxBufferHead - s->port.rxBufferTail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t uartTotalTxBytesFree(const serialPort_t *instance)
|
|
||||||
{
|
|
||||||
uartPort_t *s = (uartPort_t*)instance;
|
|
||||||
|
|
||||||
uint32_t bytesUsed;
|
|
||||||
|
|
||||||
if (s->port.txBufferHead >= s->port.txBufferTail) {
|
|
||||||
bytesUsed = s->port.txBufferHead - s->port.txBufferTail;
|
|
||||||
} else {
|
|
||||||
bytesUsed = s->port.txBufferSize + s->port.txBufferHead - s->port.txBufferTail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (s->txDMAResource) {
|
|
||||||
/*
|
|
||||||
* When we queue up a DMA request, we advance the Tx buffer tail before the transfer finishes, so we must add
|
|
||||||
* the remaining size of that in-progress transfer here instead:
|
|
||||||
*/
|
|
||||||
bytesUsed += __HAL_DMA_GET_COUNTER(s->Handle.hdmatx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the Tx buffer is being written to very quickly, we might have advanced the head into the buffer
|
|
||||||
* space occupied by the current DMA transfer. In that case the "bytesUsed" total will actually end up larger
|
|
||||||
* than the total Tx buffer size, because we'll end up transmitting the same buffer region twice. (So we'll be
|
|
||||||
* transmitting a garbage mixture of old and new bytes).
|
|
||||||
*
|
|
||||||
* Be kind to callers and pretend like our buffer can only ever be 100% full.
|
|
||||||
*/
|
|
||||||
if (bytesUsed >= s->port.txBufferSize - 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (s->port.txBufferSize - 1) - bytesUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isUartTransmitBufferEmpty(const serialPort_t *instance)
|
|
||||||
{
|
|
||||||
const uartPort_t *s = (uartPort_t *)instance;
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (s->txDMAResource)
|
|
||||||
return s->txDMAEmpty;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return s->port.txBufferTail == s->port.txBufferHead;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t uartRead(serialPort_t *instance)
|
|
||||||
{
|
|
||||||
uint8_t ch;
|
|
||||||
uartPort_t *s = (uartPort_t *)instance;
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (s->rxDMAResource) {
|
|
||||||
ch = s->port.rxBuffer[s->port.rxBufferSize - s->rxDMAPos];
|
|
||||||
if (--s->rxDMAPos == 0)
|
|
||||||
s->rxDMAPos = s->port.rxBufferSize;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
ch = s->port.rxBuffer[s->port.rxBufferTail];
|
|
||||||
if (s->port.rxBufferTail + 1 >= s->port.rxBufferSize) {
|
|
||||||
s->port.rxBufferTail = 0;
|
|
||||||
} else {
|
|
||||||
s->port.rxBufferTail++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartWrite(serialPort_t *instance, uint8_t ch)
|
|
||||||
{
|
|
||||||
uartPort_t *s = (uartPort_t *)instance;
|
|
||||||
|
|
||||||
s->port.txBuffer[s->port.txBufferHead] = ch;
|
|
||||||
|
|
||||||
if (s->port.txBufferHead + 1 >= s->port.txBufferSize) {
|
|
||||||
s->port.txBufferHead = 0;
|
|
||||||
} else {
|
|
||||||
s->port.txBufferHead++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_DMA
|
|
||||||
if (s->txDMAResource) {
|
|
||||||
uartTryStartTxDMA(s);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
__HAL_UART_ENABLE_IT(&s->Handle, UART_IT_TXE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct serialPortVTable uartVTable[] = {
|
|
||||||
{
|
|
||||||
.serialWrite = uartWrite,
|
|
||||||
.serialTotalRxWaiting = uartTotalRxBytesWaiting,
|
|
||||||
.serialTotalTxFree = uartTotalTxBytesFree,
|
|
||||||
.serialRead = uartRead,
|
|
||||||
.serialSetBaudRate = uartSetBaudRate,
|
|
||||||
.isSerialTransmitBufferEmpty = isUartTransmitBufferEmpty,
|
|
||||||
.setMode = uartSetMode,
|
|
||||||
.setCtrlLineStateCb = NULL,
|
|
||||||
.setBaudRateCb = NULL,
|
|
||||||
.writeBuf = NULL,
|
|
||||||
.beginWrite = NULL,
|
|
||||||
.endWrite = NULL,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef USE_UART1
|
|
||||||
// USART1 Rx/Tx IRQ Handler
|
|
||||||
void USART1_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_1]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART2
|
|
||||||
// USART2 Rx/Tx IRQ Handler
|
|
||||||
void USART2_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_2]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART3
|
|
||||||
// USART3 Rx/Tx IRQ Handler
|
|
||||||
void USART3_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_3]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART4
|
|
||||||
// UART4 Rx/Tx IRQ Handler
|
|
||||||
void UART4_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_4]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART5
|
|
||||||
// UART5 Rx/Tx IRQ Handler
|
|
||||||
void UART5_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_5]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART6
|
|
||||||
// USART6 Rx/Tx IRQ Handler
|
|
||||||
void USART6_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_6]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART7
|
|
||||||
// UART7 Rx/Tx IRQ Handler
|
|
||||||
void UART7_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_7]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_UART8
|
|
||||||
// UART8 Rx/Tx IRQ Handler
|
|
||||||
void UART8_IRQHandler(void)
|
|
||||||
{
|
|
||||||
uartPort_t *s = &(uartDevmap[UARTDEV_8]->port);
|
|
||||||
uartIrqHandler(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -37,9 +37,11 @@
|
||||||
#ifdef USE_UART
|
#ifdef USE_UART
|
||||||
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
#include "build/atomic.h"
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
#include "drivers/inverter.h"
|
#include "drivers/inverter.h"
|
||||||
|
#include "drivers/nvic.h"
|
||||||
#include "drivers/rcc.h"
|
#include "drivers/rcc.h"
|
||||||
|
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
|
@ -114,137 +116,140 @@ void uartReconfigure(uartPort_t *uartPort)
|
||||||
USART_HalfDuplexCmd(uartPort->USARTx, DISABLE);
|
USART_HalfDuplexCmd(uartPort->USARTx, DISABLE);
|
||||||
|
|
||||||
USART_Cmd(uartPort->USARTx, ENABLE);
|
USART_Cmd(uartPort->USARTx, ENABLE);
|
||||||
}
|
|
||||||
|
|
||||||
serialPort_t *uartOpen(UARTDevice_e device, serialReceiveCallbackPtr rxCallback, void *rxCallbackData, uint32_t baudRate, portMode_e mode, portOptions_e options)
|
|
||||||
{
|
|
||||||
uartPort_t *s = serialUART(device, baudRate, mode, options);
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
return (serialPort_t *)s;
|
|
||||||
|
|
||||||
s->txDMAEmpty = true;
|
|
||||||
|
|
||||||
// common serial initialisation code should move to serialPort::init()
|
|
||||||
s->port.rxBufferHead = s->port.rxBufferTail = 0;
|
|
||||||
s->port.txBufferHead = s->port.txBufferTail = 0;
|
|
||||||
// callback works for IRQ-based RX ONLY
|
|
||||||
s->port.rxCallback = rxCallback;
|
|
||||||
s->port.rxCallbackData = rxCallbackData;
|
|
||||||
s->port.mode = mode;
|
|
||||||
s->port.baudRate = baudRate;
|
|
||||||
s->port.options = options;
|
|
||||||
|
|
||||||
uartReconfigure(s);
|
|
||||||
|
|
||||||
// Receive DMA or IRQ
|
// Receive DMA or IRQ
|
||||||
DMA_InitTypeDef DMA_InitStructure;
|
DMA_InitTypeDef DMA_InitStructure;
|
||||||
if (mode & MODE_RX) {
|
if (uartPort->port.mode & MODE_RX) {
|
||||||
#ifdef STM32F4
|
if (uartPort->rxDMAResource) {
|
||||||
if (s->rxDMAResource) {
|
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
DMA_StructInit(&DMA_InitStructure);
|
||||||
DMA_InitStructure.DMA_PeripheralBaseAddr = s->rxDMAPeripheralBaseAddr;
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||||
|
DMA_InitStructure.DMA_PeripheralBaseAddr = uartPort->rxDMAPeripheralBaseAddr;
|
||||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
||||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||||
|
DMA_InitStructure.DMA_BufferSize = uartPort->port.rxBufferSize;
|
||||||
|
#ifdef STM32F4
|
||||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
|
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
|
||||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
|
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
|
||||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
|
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
|
||||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||||
#else
|
|
||||||
if (s->rxDMAResource) {
|
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
|
||||||
DMA_InitStructure.DMA_PeripheralBaseAddr = s->rxDMAPeripheralBaseAddr;
|
|
||||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
|
||||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
|
||||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
||||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
||||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
||||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
||||||
#endif
|
|
||||||
DMA_InitStructure.DMA_BufferSize = s->port.rxBufferSize;
|
|
||||||
|
|
||||||
#ifdef STM32F4
|
DMA_InitStructure.DMA_Channel = uartPort->rxDMAChannel;
|
||||||
DMA_InitStructure.DMA_Channel = s->rxDMAChannel;
|
|
||||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)uartPort->port.rxBuffer;
|
||||||
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)s->port.rxBuffer;
|
|
||||||
xDMA_DeInit(s->rxDMAResource);
|
|
||||||
xDMA_Init(s->rxDMAResource, &DMA_InitStructure);
|
|
||||||
xDMA_Cmd(s->rxDMAResource, ENABLE);
|
|
||||||
USART_DMACmd(s->USARTx, USART_DMAReq_Rx, ENABLE);
|
|
||||||
s->rxDMAPos = xDMA_GetCurrDataCounter(s->rxDMAResource);
|
|
||||||
#else
|
#else
|
||||||
|
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uartPort->port.rxBuffer;
|
||||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)s->port.rxBuffer;
|
|
||||||
xDMA_DeInit(s->rxDMAResource);
|
|
||||||
xDMA_Init(s->rxDMAResource, &DMA_InitStructure);
|
|
||||||
xDMA_Cmd(s->rxDMAResource, ENABLE);
|
|
||||||
USART_DMACmd(s->USARTx, USART_DMAReq_Rx, ENABLE);
|
|
||||||
s->rxDMAPos = xDMA_GetCurrDataCounter(s->rxDMAResource);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
xDMA_DeInit(uartPort->rxDMAResource);
|
||||||
|
xDMA_Init(uartPort->rxDMAResource, &DMA_InitStructure);
|
||||||
|
xDMA_Cmd(uartPort->rxDMAResource, ENABLE);
|
||||||
|
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Rx, ENABLE);
|
||||||
|
uartPort->rxDMAPos = xDMA_GetCurrDataCounter(uartPort->rxDMAResource);
|
||||||
} else {
|
} else {
|
||||||
USART_ClearITPendingBit(s->USARTx, USART_IT_RXNE);
|
USART_ClearITPendingBit(uartPort->USARTx, USART_IT_RXNE);
|
||||||
USART_ITConfig(s->USARTx, USART_IT_RXNE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_RXNE, ENABLE);
|
||||||
USART_ITConfig(s->USARTx, USART_IT_IDLE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_IDLE, ENABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit DMA or IRQ
|
// Transmit DMA or IRQ
|
||||||
if (mode & MODE_TX) {
|
if (uartPort->port.mode & MODE_TX) {
|
||||||
#ifdef STM32F4
|
if (uartPort->txDMAResource) {
|
||||||
if (s->txDMAResource) {
|
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
DMA_StructInit(&DMA_InitStructure);
|
||||||
DMA_InitStructure.DMA_PeripheralBaseAddr = s->txDMAPeripheralBaseAddr;
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||||
|
DMA_InitStructure.DMA_PeripheralBaseAddr = uartPort->txDMAPeripheralBaseAddr;
|
||||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
||||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||||
|
DMA_InitStructure.DMA_BufferSize = uartPort->port.txBufferSize;
|
||||||
|
|
||||||
|
#ifdef STM32F4
|
||||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
|
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
|
||||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
|
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
|
||||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
|
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
|
||||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||||
|
|
||||||
|
DMA_InitStructure.DMA_Channel = uartPort->txDMAChannel;
|
||||||
|
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||||
#else
|
#else
|
||||||
if (s->txDMAResource) {
|
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
|
||||||
DMA_InitStructure.DMA_PeripheralBaseAddr = s->txDMAPeripheralBaseAddr;
|
|
||||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
|
||||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
||||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
||||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
||||||
#endif
|
#endif
|
||||||
DMA_InitStructure.DMA_BufferSize = s->port.txBufferSize;
|
|
||||||
|
xDMA_DeInit(uartPort->txDMAResource);
|
||||||
|
xDMA_Init(uartPort->txDMAResource, &DMA_InitStructure);
|
||||||
|
|
||||||
#ifdef STM32F4
|
#ifdef STM32F4
|
||||||
DMA_InitStructure.DMA_Channel = s->txDMAChannel;
|
xDMA_ITConfig(uartPort->txDMAResource, DMA_IT_TC | DMA_IT_FE | DMA_IT_TE | DMA_IT_DME, ENABLE);
|
||||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
|
||||||
xDMA_DeInit(s->txDMAResource);
|
|
||||||
xDMA_Init(s->txDMAResource, &DMA_InitStructure);
|
|
||||||
xDMA_ITConfig(s->txDMAResource, DMA_IT_TC | DMA_IT_FE | DMA_IT_TE | DMA_IT_DME, ENABLE);
|
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, 0);
|
|
||||||
#else
|
#else
|
||||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
xDMA_ITConfig(uartPort->txDMAResource, DMA_IT_TC, ENABLE);
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
|
||||||
xDMA_DeInit(s->txDMAResource);
|
|
||||||
xDMA_Init(s->txDMAResource, &DMA_InitStructure);
|
|
||||||
xDMA_ITConfig(s->txDMAResource, DMA_IT_TC, ENABLE);
|
|
||||||
xDMA_SetCurrDataCounter(s->txDMAResource, 0);
|
|
||||||
#endif
|
#endif
|
||||||
USART_DMACmd(s->USARTx, USART_DMAReq_Tx, ENABLE);
|
|
||||||
|
xDMA_SetCurrDataCounter(uartPort->txDMAResource, 0);
|
||||||
|
USART_DMACmd(uartPort->USARTx, USART_DMAReq_Tx, ENABLE);
|
||||||
} else {
|
} else {
|
||||||
USART_ITConfig(s->USARTx, USART_IT_TXE, ENABLE);
|
USART_ITConfig(uartPort->USARTx, USART_IT_TXE, ENABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
USART_Cmd(s->USARTx, ENABLE);
|
USART_Cmd(uartPort->USARTx, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
return (serialPort_t *)s;
|
#ifdef USE_DMA
|
||||||
|
void uartTryStartTxDMA(uartPort_t *s)
|
||||||
|
{
|
||||||
|
// uartTryStartTxDMA must be protected, since it is called from
|
||||||
|
// uartWrite and handleUsartTxDma (an ISR).
|
||||||
|
|
||||||
|
ATOMIC_BLOCK(NVIC_PRIO_SERIALUART_TXDMA) {
|
||||||
|
if (IS_DMA_ENABLED(s->txDMAResource)) {
|
||||||
|
// DMA is already in progress
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For F4 (and F1), there are cases that NDTR (CNDTR for F1) is non-zero upon TC interrupt.
|
||||||
|
// We couldn't find out the root cause, so mask the case here.
|
||||||
|
// F3 is not confirmed to be vulnerable, but not excluded as a safety.
|
||||||
|
|
||||||
|
if (xDMA_GetCurrDataCounter(s->txDMAResource)) {
|
||||||
|
// Possible premature TC case.
|
||||||
|
goto reenable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->port.txBufferHead == s->port.txBufferTail) {
|
||||||
|
// No more data to transmit.
|
||||||
|
s->txDMAEmpty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a new transaction.
|
||||||
|
|
||||||
|
#ifdef STM32F4
|
||||||
|
xDMA_MemoryTargetConfig(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail], DMA_Memory_0);
|
||||||
|
#else
|
||||||
|
DMAx_SetMemoryAddress(s->txDMAResource, (uint32_t)&s->port.txBuffer[s->port.txBufferTail]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (s->port.txBufferHead > s->port.txBufferTail) {
|
||||||
|
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferHead - s->port.txBufferTail);
|
||||||
|
s->port.txBufferTail = s->port.txBufferHead;
|
||||||
|
} else {
|
||||||
|
xDMA_SetCurrDataCounter(s->txDMAResource, s->port.txBufferSize - s->port.txBufferTail);
|
||||||
|
s->port.txBufferTail = 0;
|
||||||
|
}
|
||||||
|
s->txDMAEmpty = false;
|
||||||
|
|
||||||
|
reenable:
|
||||||
|
xDMA_Cmd(s->txDMAResource, ENABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // USE_UART
|
Loading…
Add table
Add a link
Reference in a new issue