arch/arm/stm32h5: Add DMA Support to STM32H5 Serial Driver
Style fixes.
This commit is contained in:
parent
ec64401c62
commit
4995c836f3
5 changed files with 304 additions and 222 deletions
|
|
@ -4397,6 +4397,13 @@ config LPUART1_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on LPUART1. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config LPUART1_RXDMA
|
||||
bool "LPUART1 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_LPUART1 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # LPUART1_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4431,6 +4438,13 @@ config USART1_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART1. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART1_RXDMA
|
||||
bool "USART1 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART1 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART1_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4465,6 +4479,13 @@ config USART2_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART2. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART2_RXDMA
|
||||
bool "USART2 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART2 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART2_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4499,6 +4520,13 @@ config USART3_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART3. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART3_RXDMA
|
||||
bool "USART3 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART3 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART3_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4533,6 +4561,13 @@ config UART4_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART4. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART4_RXDMA
|
||||
bool "UART4 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART4 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART4_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4567,6 +4602,13 @@ config UART5_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART5. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART5_RXDMA
|
||||
bool "UART5 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART5 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART5_SERIALDRIVER
|
||||
|
||||
choice
|
||||
|
|
@ -4601,6 +4643,13 @@ config USART6_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART6. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART6_RXDMA
|
||||
bool "USART6 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART6 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART6_SERIALDRIVER
|
||||
|
||||
if UART7_SERIALDRIVER
|
||||
|
|
@ -4623,6 +4672,13 @@ config UART7_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART7. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART7_RXDMA
|
||||
bool "UART7 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART7 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART7_SERIALDRIVER
|
||||
|
||||
if UART8_SERIALDRIVER
|
||||
|
|
@ -4645,6 +4701,13 @@ config UART8_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART8. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART8_RXDMA
|
||||
bool "UART8 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART8 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART8_SERIALDRIVER
|
||||
|
||||
if UART9_SERIALDRIVER
|
||||
|
|
@ -4667,6 +4730,13 @@ config UART9_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART9. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART9_RXDMA
|
||||
bool "UART9 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART9 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART9_SERIALDRIVER
|
||||
|
||||
if USART10_SERIALDRIVER
|
||||
|
|
@ -4689,6 +4759,13 @@ config USART10_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART10. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART10_RXDMA
|
||||
bool "USART10 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART10 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART10_SERIALDRIVER
|
||||
|
||||
if USART11_SERIALDRIVER
|
||||
|
|
@ -4711,6 +4788,13 @@ config USART11_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on USART11. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config USART11_RXDMA
|
||||
bool "USART11 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_USART11 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # USART11_SERIALDRIVER
|
||||
|
||||
if UART12_SERIALDRIVER
|
||||
|
|
@ -4733,12 +4817,33 @@ config UART12_RS485_DIR_POLARITY
|
|||
Polarity of DIR pin for RS-485 on UART12. Set to state on DIR pin which
|
||||
enables TX (0 - low / nTXEN, 1 - high / TXEN).
|
||||
|
||||
config UART12_RXDMA
|
||||
bool "UART12 RX DMA"
|
||||
default n
|
||||
depends on STM32H5_UART12 && (STM32H5_DMA1 || STM32H5_DMA2)
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
endif # UART12_SERIALDRIVER
|
||||
|
||||
if STM32H5_SERIALDRIVER
|
||||
|
||||
comment "Serial Driver Configuration"
|
||||
|
||||
config STM32H5_SERIAL_RXDMA_BUFFER_SIZE
|
||||
int "Rx DMA buffer size"
|
||||
default 32
|
||||
depends on USART1_RXDMA || USART2_RXDMA || USART3_RXDMA || USART6_RXDMA || USART10_RXDMA || \
|
||||
USART11_RXDMA || UART4_RXDMA || UART5_RXDMA || UART7_RXDMA || UART8_RXDMA || \
|
||||
UART9_RXDMA || UART12_RXDMA || LPUART1_RXDMA
|
||||
---help---
|
||||
The DMA buffer size when using RX DMA to emulate a FIFO.
|
||||
|
||||
When streaming data, the generic serial layer will be called
|
||||
every time the FIFO receives half this number of bytes.
|
||||
|
||||
Value given here will be rounded up to next multiple of 32 bytes.
|
||||
|
||||
config STM32H5_SERIAL_DISABLE_REORDERING
|
||||
bool "Disable reordering of ttySx devices."
|
||||
depends on STM32H5_USART1 || STM32H5_USART2 || STM32H5_USART3 || STM32H5_UART4 || STM32H5_UART5
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@
|
|||
#define GPDMA_REQ_UART8_TX (36)
|
||||
#define GPDMA_REQ_UART9_RX (37)
|
||||
#define GPDMA_REQ_UART9_TX (38)
|
||||
#define GPDMA_REQ_UART10_RX (39)
|
||||
#define GPDMA_REQ_UART10_TX (40)
|
||||
#define GPDMA_REQ_UART11_RX (41)
|
||||
#define GPDMA_REQ_UART11_TX (42)
|
||||
#define GPDMA_REQ_USART10_RX (39)
|
||||
#define GPDMA_REQ_USART10_TX (40)
|
||||
#define GPDMA_REQ_USART11_RX (41)
|
||||
#define GPDMA_REQ_USART11_TX (42)
|
||||
#define GPDMA_REQ_UART12_RX (43)
|
||||
#define GPDMA_REQ_UART12_TX (44)
|
||||
#define GPDMA_REQ_LPUART1_RX (45)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
* off this in this file.
|
||||
*/
|
||||
|
||||
#define CH_BASE_OFFSET(ch) (0x80*(ch))
|
||||
#define CH_BASE_OFFSET(ch) (0x80*(ch))
|
||||
#define CH_CXLBAR_OFFSET 0x50
|
||||
#define CH_CXFCR_OFFSET 0x5C
|
||||
#define CH_CXSR_OFFSET 0x60
|
||||
|
|
@ -694,6 +694,31 @@ void stm32_dmastop(DMA_HANDLE handle)
|
|||
/* gpdma_ch_abort(chan); */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmaresidual
|
||||
*
|
||||
* Description:
|
||||
* Returns the number of data beats remaining to transfer in the current
|
||||
* STM32H5 GPDMA block. This reads the BNDT[15:0] field from the
|
||||
* GPDMA_CxBR1 register, which indicates how many beats are left in the
|
||||
* programmed transfer.
|
||||
*
|
||||
* Assumptions:
|
||||
* - DMA handle was allocated by stm32_dmachannel().
|
||||
* - The handle refers to a valid STM32H5 GPDMA channel.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t stm32_dmaresidual(DMA_HANDLE handle)
|
||||
{
|
||||
struct gpdma_ch_s *chan = (struct gpdma_ch_s *)handle;
|
||||
uint32_t br1 = getreg32(chan->base + CH_CXBR1_OFFSET);
|
||||
|
||||
/* BNDT[15:0] = beats remaining in current block transfer */
|
||||
|
||||
return (size_t)(br1 & GPDMA_CXBR1_BNDT_MASK);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STM32H5_DMACAPABLE
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmacapable
|
||||
|
|
@ -760,4 +785,4 @@ void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs)
|
|||
{
|
||||
#warning "stm32_dmasample() not implemented yet!"
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -52,13 +52,7 @@
|
|||
#include "chip.h"
|
||||
#include "stm32_gpio.h"
|
||||
#include "stm32_uart.h"
|
||||
|
||||
/* DMA has not been implemented for H5 chip yet, so disable any serial DMA */
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
# error Serial DMA not implemented for STM32H5 chips.
|
||||
#undef SERIAL_HAVE_DMA
|
||||
#endif
|
||||
#include "stm32_dma.h"
|
||||
|
||||
#include "stm32_rcc.h"
|
||||
#include "arm_internal.h"
|
||||
|
|
@ -81,22 +75,18 @@
|
|||
* 5 X
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
# warning STM32H5 Serial IFLOWCONTROL is untested
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
|
||||
/* Verify that DMA has been enabled and the DMA channel has been defined.
|
||||
*/
|
||||
|
||||
# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA)
|
||||
# if !defined(CONFIG_STM32H5_DMA1) && !defined(CONFIG_STM32H5_DMAMUX)
|
||||
# error STM32H5 USART2/3 receive DMA requires CONFIG_STM32H5_DMA1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_UART4_RXDMA) || defined(CONFIG_UART5_RXDMA)
|
||||
# if !defined(CONFIG_STM32H5_DMA2) && !defined(CONFIG_STM32H5_DMAMUX)
|
||||
# error STM32H5 UART4/5 receive DMA requires CONFIG_STM32H5_DMA2
|
||||
# endif
|
||||
# endif
|
||||
#if !defined(CONFIG_STM32H5_DMA1) && !defined(CONFIG_STM32H5_DMA2)
|
||||
# error STM32H5 Serial DMA requires one of DMA1 or DMA2 to be enabled
|
||||
#endif
|
||||
|
||||
/* Currently RS-485 support cannot be enabled when RXDMA is in use due to
|
||||
* lack of testing - RS-485 support was developed on STM32F1x
|
||||
|
|
@ -110,40 +100,6 @@
|
|||
# error "RXDMA and RS-485 cannot be enabled at the same time for the same U[S]ART"
|
||||
# endif
|
||||
|
||||
/* For the L4, there are alternate DMA channels for USART1.
|
||||
* Logic in the board.h file make the DMA channel selection by defining
|
||||
* the following in the board.h file.
|
||||
*/
|
||||
|
||||
# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
|
||||
# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
|
||||
# endif
|
||||
|
||||
/* UART2-5 have no alternate channels without DMAMUX */
|
||||
|
||||
# ifndef CONFIG_STM32H5_HAVE_DMAMUX
|
||||
# define DMAMAP_USART2_RX DMACHAN_USART2_RX
|
||||
# define DMAMAP_USART3_RX DMACHAN_USART3_RX
|
||||
# define DMAMAP_UART4_RX DMACHAN_UART4_RX
|
||||
# define DMAMAP_UART5_RX DMACHAN_UART5_RX
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
|
||||
# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
|
||||
# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX)
|
||||
# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX)
|
||||
# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
|
||||
# endif
|
||||
|
||||
/* The DMA buffer size when using RX DMA to emulate a FIFO.
|
||||
*
|
||||
* When streaming data, the generic serial layer will be called
|
||||
|
|
@ -161,31 +117,6 @@
|
|||
# define RXDMA_BUFFER_SIZE ((CONFIG_STM32H5_SERIAL_RXDMA_BUFFER_SIZE + 31) & ~31)
|
||||
# endif
|
||||
|
||||
/* DMA priority */
|
||||
|
||||
# ifndef CONFIG_USART_DMAPRIO
|
||||
# define CONFIG_USART_DMAPRIO DMA_CCR_PRIMED
|
||||
# endif
|
||||
# if (CONFIG_USART_DMAPRIO & ~DMA_CCR_PL_MASK) != 0
|
||||
# error "Illegal value for CONFIG_USART_DMAPRIO"
|
||||
# endif
|
||||
|
||||
/* DMA control words */
|
||||
|
||||
# define SERIAL_DMA_CONTROL_WORD \
|
||||
(DMA_CCR_CIRC | \
|
||||
DMA_CCR_MINC | \
|
||||
DMA_CCR_PSIZE_8BITS | \
|
||||
DMA_CCR_MSIZE_8BITS | \
|
||||
CONFIG_USART_DMAPRIO)
|
||||
# ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
# define SERIAL_DMA_IFLOW_CONTROL_WORD \
|
||||
(DMA_CCR_MINC | \
|
||||
DMA_CCR_PSIZE_8BITS | \
|
||||
DMA_CCR_MSIZE_8BITS | \
|
||||
CONFIG_USART_DMAPRIO)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Power management definitions */
|
||||
|
|
@ -243,9 +174,6 @@ struct stm32_serial_s
|
|||
uint8_t parity; /* 0=none, 1=odd, 2=even */
|
||||
uint8_t bits; /* Number of bits (7 or 8) */
|
||||
bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
bool iflow; /* input flow control (RTS) enabled */
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_OFLOWCONTROL
|
||||
bool oflow; /* output flow control (CTS) enabled */
|
||||
#endif
|
||||
|
|
@ -254,15 +182,11 @@ struct stm32_serial_s
|
|||
const uint8_t parity; /* 0=none, 1=odd, 2=even */
|
||||
const uint8_t bits; /* Number of bits (7 or 8) */
|
||||
const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
const bool iflow; /* input flow control (RTS) enabled */
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_OFLOWCONTROL
|
||||
const bool oflow; /* output flow control (CTS) enabled */
|
||||
#endif
|
||||
const uint32_t baud; /* Configured baud */
|
||||
#endif
|
||||
|
||||
const uint8_t irq; /* IRQ associated with this USART */
|
||||
const uint32_t apbclock; /* PCLK 1 or 2 frequency */
|
||||
const uint32_t usartbase; /* Base address of USART registers */
|
||||
|
|
@ -274,10 +198,7 @@ struct stm32_serial_s
|
|||
#ifdef CONFIG_SERIAL_OFLOWCONTROL
|
||||
const uint32_t cts_gpio; /* U[S]ART CTS GPIO pin configuration */
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
const unsigned int rxdma_channel; /* DMA channel assigned */
|
||||
#endif
|
||||
const bool iflow; /* input flow control (RTS) enabled */
|
||||
|
||||
/* RX DMA state */
|
||||
|
||||
|
|
@ -288,7 +209,8 @@ struct stm32_serial_s
|
|||
bool rxdmasusp; /* Rx DMA suspended */
|
||||
#endif
|
||||
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
|
||||
char *const rxfifo; /* Receive DMA buffer */
|
||||
uint16_t rxdma_req; /* GPDMA Request number */
|
||||
char *const rxfifo; /* Receive DMA buffer */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RS485
|
||||
|
|
@ -543,8 +465,8 @@ static struct stm32_serial_s g_lpuart1priv =
|
|||
.rts_gpio = GPIO_LPUART1_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_LPUART1_RXDMA
|
||||
.rxdma_channel = DMAMAP_LPUSART_RX,
|
||||
.rxfifo = g_lpuart1rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_LPUART1_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART1_RS485
|
||||
|
|
@ -604,8 +526,8 @@ static struct stm32_serial_s g_usart1priv =
|
|||
.rts_gpio = GPIO_USART1_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART1_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART1_RX,
|
||||
.rxfifo = g_usart1rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART1_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART1_RS485
|
||||
|
|
@ -667,8 +589,8 @@ static struct stm32_serial_s g_usart2priv =
|
|||
.rts_gpio = GPIO_USART2_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART2_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART2_RX,
|
||||
.rxfifo = g_usart2rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART2_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART2_RS485
|
||||
|
|
@ -730,8 +652,8 @@ static struct stm32_serial_s g_usart3priv =
|
|||
.rts_gpio = GPIO_USART3_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART3_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART3_RX,
|
||||
.rxfifo = g_usart3rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART3_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART3_RS485
|
||||
|
|
@ -793,8 +715,8 @@ static struct stm32_serial_s g_uart4priv =
|
|||
.tx_gpio = GPIO_UART4_TX,
|
||||
.rx_gpio = GPIO_UART4_RX,
|
||||
# ifdef CONFIG_UART4_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART4_RX,
|
||||
.rxfifo = g_uart4rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART4_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART4_RS485
|
||||
|
|
@ -856,8 +778,8 @@ static struct stm32_serial_s g_uart5priv =
|
|||
.tx_gpio = GPIO_UART5_TX,
|
||||
.rx_gpio = GPIO_UART5_RX,
|
||||
# ifdef CONFIG_UART5_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART5_RX,
|
||||
.rxfifo = g_uart5rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART5_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART5_RS485
|
||||
|
|
@ -919,8 +841,8 @@ static struct stm32_serial_s g_usart6priv =
|
|||
.rts_gpio = GPIO_USART6_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART6_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART6_RX,
|
||||
.rxfifo = g_usart6rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART6_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART6_RS485
|
||||
|
|
@ -982,8 +904,8 @@ static struct stm32_serial_s g_uart7priv =
|
|||
.tx_gpio = GPIO_UART7_TX,
|
||||
.rx_gpio = GPIO_UART7_RX,
|
||||
# ifdef CONFIG_UART7_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART7_RX,
|
||||
.rxfifo = g_uart7rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART7_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART7_RS485
|
||||
|
|
@ -1045,8 +967,8 @@ static struct stm32_serial_s g_uart8priv =
|
|||
.tx_gpio = GPIO_UART8_TX,
|
||||
.rx_gpio = GPIO_UART8_RX,
|
||||
# ifdef CONFIG_UART8_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART8_RX,
|
||||
.rxfifo = g_uart8rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART8_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART8_RS485
|
||||
|
|
@ -1108,8 +1030,8 @@ static struct stm32_serial_s g_uart9priv =
|
|||
.tx_gpio = GPIO_UART9_TX,
|
||||
.rx_gpio = GPIO_UART9_RX,
|
||||
# ifdef CONFIG_UART9_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART9_RX,
|
||||
.rxfifo = g_uart9rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART9_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART9_RS485
|
||||
|
|
@ -1171,8 +1093,8 @@ static struct stm32_serial_s g_usart10priv =
|
|||
.rts_gpio = GPIO_USART10_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART10_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART10_RX,
|
||||
.rxfifo = g_usart10rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART10_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART10_RS485
|
||||
|
|
@ -1234,8 +1156,8 @@ static struct stm32_serial_s g_usart11priv =
|
|||
.rts_gpio = GPIO_USART11_RTS,
|
||||
# endif
|
||||
# ifdef CONFIG_USART11_RXDMA
|
||||
.rxdma_channel = DMAMAP_USART11_RX,
|
||||
.rxfifo = g_usart11rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_USART11_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_USART11_RS485
|
||||
|
|
@ -1297,8 +1219,8 @@ static struct stm32_serial_s g_uart12priv =
|
|||
.tx_gpio = GPIO_UART12_TX,
|
||||
.rx_gpio = GPIO_UART12_RX,
|
||||
# ifdef CONFIG_UART12_RXDMA
|
||||
.rxdma_channel = DMAMAP_UART12_RX,
|
||||
.rxfifo = g_uart12rxfifo,
|
||||
.rxdma_req = GPDMA_REQ_UART12_RX,
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_UART12_RS485
|
||||
|
|
@ -2166,69 +2088,88 @@ static int stm32serial_setup(struct uart_dev_s *dev)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: serial_rxdmacfg
|
||||
*
|
||||
* Description:
|
||||
* Generate the required DMA configuration structure for oneshot mode based
|
||||
* on the serial configuration.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - serial instance structure
|
||||
* cfg - DMA configuration structure
|
||||
* circular - 0 = oneshot, 1 = circular
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
static void serial_rxdmacfg(struct stm32_serial_s *priv,
|
||||
struct stm32_gpdma_cfg_s *cfg)
|
||||
{
|
||||
cfg->src_addr = priv->usartbase + STM32_USART_RDR_OFFSET;
|
||||
cfg->dest_addr = (uint32_t)priv->rxfifo;
|
||||
|
||||
cfg->request = priv->rxdma_req;
|
||||
|
||||
cfg->priority = GPMDACFG_PRIO_LH;
|
||||
|
||||
cfg->mode = GPDMACFG_MODE_CIRC;
|
||||
|
||||
cfg->ntransfers = RXDMA_BUFFER_SIZE;
|
||||
|
||||
/* Write SDW and DDW to 0 for 8-bit beats */
|
||||
|
||||
cfg->tr1 = GPDMA_CXTR1_DINC; /* dest-inc, source fixed */
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32serial_dmasetup
|
||||
*
|
||||
* Description:
|
||||
* Configure the USART baud, bits, parity, etc. This method is called the
|
||||
* first time that the serial port is opened.
|
||||
* Configure and start circular RX DMA for USART:
|
||||
* - Allocate a GPDMA channel
|
||||
* - Set up source (USART RDR), destination (RX buffer), REQSEL,
|
||||
* circular mode
|
||||
* - Program DMA and reset read index
|
||||
* - Enable USART CR3.DMAR
|
||||
* - Start DMA with half‑ and full‑transfer callbacks
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; negative errno on failure.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
static int stm32serial_dmasetup(struct uart_dev_s *dev)
|
||||
{
|
||||
struct stm32_serial_s *priv =
|
||||
(struct stm32_serial_s *)dev->priv;
|
||||
int result;
|
||||
uint32_t regval;
|
||||
|
||||
/* Do the basic UART setup first, unless we are the console */
|
||||
struct stm32_serial_s *priv = (struct stm32_serial_s *)dev->priv;
|
||||
struct stm32_gpdma_cfg_s dmacfg;
|
||||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
if (!dev->isconsole)
|
||||
{
|
||||
result = stm32serial_setup(dev);
|
||||
if (result != OK)
|
||||
ret = stm32serial_setup(dev);
|
||||
if (ret != OK)
|
||||
{
|
||||
return result;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire the DMA channel. This should always succeed. */
|
||||
|
||||
priv->rxdma = stm32h5_dmachannel(priv->rxdma_channel);
|
||||
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
if (priv->iflow)
|
||||
priv->rxdma = stm32_dmachannel(GPDMA_TTYPE_P2M);
|
||||
if (!priv->rxdma)
|
||||
{
|
||||
/* Configure for non-circular DMA reception into the RX FIFO */
|
||||
|
||||
stm32h5_dmasetup(priv->rxdma,
|
||||
priv->usartbase + STM32_USART_RDR_OFFSET,
|
||||
(uint32_t)priv->rxfifo,
|
||||
RXDMA_BUFFER_SIZE,
|
||||
SERIAL_DMA_IFLOW_CONTROL_WORD);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Configure for circular DMA reception into the RX FIFO */
|
||||
|
||||
stm32h5_dmasetup(priv->rxdma,
|
||||
priv->usartbase + STM32_USART_RDR_OFFSET,
|
||||
(uint32_t)priv->rxfifo,
|
||||
RXDMA_BUFFER_SIZE,
|
||||
SERIAL_DMA_CONTROL_WORD);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Reset our DMA shadow pointer to match the address just
|
||||
* programmed above.
|
||||
*/
|
||||
serial_rxdmacfg(priv, &dmacfg);
|
||||
|
||||
stm32_dmasetup(priv->rxdma, &dmacfg);
|
||||
|
||||
priv->rxdmanext = 0;
|
||||
|
||||
/* Enable receive DMA for the UART */
|
||||
|
||||
regval = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET);
|
||||
regval |= USART_CR3_DMAR;
|
||||
stm32serial_putreg(priv, STM32_USART_CR3_OFFSET, regval);
|
||||
|
|
@ -2241,8 +2182,8 @@ static int stm32serial_dmasetup(struct uart_dev_s *dev)
|
|||
* in and DMA transfer is stopped.
|
||||
*/
|
||||
|
||||
stm32h5_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, false);
|
||||
stm32_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, false);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -2252,8 +2193,8 @@ static int stm32serial_dmasetup(struct uart_dev_s *dev)
|
|||
* worth of time to claim bytes before they are overwritten.
|
||||
*/
|
||||
|
||||
stm32h5_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, true);
|
||||
stm32_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, true);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
|
@ -2347,11 +2288,13 @@ static void stm32serial_dmashutdown(struct uart_dev_s *dev)
|
|||
|
||||
/* Stop the DMA channel */
|
||||
|
||||
stm32h5_dmastop(priv->rxdma);
|
||||
stm32_dmastop(priv->rxdma);
|
||||
|
||||
priv->rxenable = false;
|
||||
|
||||
/* Release the DMA channel */
|
||||
|
||||
stm32h5_dmafree(priv->rxdma);
|
||||
stm32_dmafree(priv->rxdma);
|
||||
priv->rxdma = NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -3131,43 +3074,64 @@ static bool stm32serial_rxflowcontrol(struct uart_dev_s *dev,
|
|||
* Name: stm32serial_dmareceive
|
||||
*
|
||||
* Description:
|
||||
* Called (usually) from the interrupt level to receive one
|
||||
* character from the USART. Error bits associated with the
|
||||
* receipt are provided in the return 'status'.
|
||||
* Retrieve one character from the RX FIFO filled by circular DMA. Also
|
||||
* report any USART error flags in *status.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
static int stm32serial_dmareceive(struct uart_dev_s *dev,
|
||||
unsigned int *status)
|
||||
unsigned int *status)
|
||||
{
|
||||
struct stm32_serial_s *priv =
|
||||
(struct stm32_serial_s *)dev->priv;
|
||||
int c = 0;
|
||||
unsigned int next;
|
||||
int ch = -1;
|
||||
uint32_t sr;
|
||||
|
||||
if (stm32serial_dmanextrx(priv) != priv->rxdmanext)
|
||||
/* 1) Capture USART error flags */
|
||||
|
||||
sr = getreg32(priv->usartbase + STM32_USART_ISR_OFFSET);
|
||||
*status = sr & (USART_ISR_ORE | USART_ISR_NF |
|
||||
USART_ISR_FE | USART_ISR_PE);
|
||||
|
||||
/* 2) Where will DMA write the next byte? */
|
||||
|
||||
next = stm32serial_dmanextrx(priv);
|
||||
|
||||
/* 3) Pull one byte if available */
|
||||
|
||||
if (next != priv->rxdmanext)
|
||||
{
|
||||
c = priv->rxfifo[priv->rxdmanext];
|
||||
ch = priv->rxfifo[priv->rxdmanext++];
|
||||
|
||||
priv->rxdmanext++;
|
||||
if (priv->rxdmanext == RXDMA_BUFFER_SIZE)
|
||||
/* 4) End‑of‑buffer wrap or flow‑control pause */
|
||||
|
||||
if (priv->rxdmanext >= RXDMA_BUFFER_SIZE)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
if (priv->iflow)
|
||||
{
|
||||
/* RX DMA buffer full. RX paused, RTS line pulled up to prevent
|
||||
* more input data from other end.
|
||||
*/
|
||||
/* Pause DMA callbacks */
|
||||
|
||||
stm32serial_dmarxint(&priv->dev, false);
|
||||
|
||||
/* Assert RTS to halt sender */
|
||||
|
||||
(void)stm32serial_rxflowcontrol(&priv->dev,
|
||||
RXDMA_BUFFER_SIZE, true);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Simply wrap to buffer start */
|
||||
|
||||
priv->rxdmanext = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
return ch;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -3182,28 +3146,10 @@ static int stm32serial_dmareceive(struct uart_dev_s *dev,
|
|||
#if defined(SERIAL_HAVE_DMA)
|
||||
static void stm32serial_dmareenable(struct stm32_serial_s *priv)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
if (priv->iflow)
|
||||
{
|
||||
/* Configure for non-circular DMA reception into the RX FIFO */
|
||||
struct stm32_gpdma_cfg_s dmacfg;
|
||||
|
||||
stm32h5_dmasetup(priv->rxdma,
|
||||
priv->usartbase + STM32_USART_RDR_OFFSET,
|
||||
(uint32_t)priv->rxfifo,
|
||||
RXDMA_BUFFER_SIZE,
|
||||
SERIAL_DMA_IFLOW_CONTROL_WORD);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Configure for circular DMA reception into the RX FIFO */
|
||||
|
||||
stm32h5_dmasetup(priv->rxdma,
|
||||
priv->usartbase + STM32_USART_RDR_OFFSET,
|
||||
(uint32_t)priv->rxfifo,
|
||||
RXDMA_BUFFER_SIZE,
|
||||
SERIAL_DMA_CONTROL_WORD);
|
||||
}
|
||||
serial_rxdmacfg(priv, &dmacfg);
|
||||
stm32_dmasetup(priv->rxdma, &dmacfg);
|
||||
|
||||
/* Reset our DMA shadow pointer to match the address just
|
||||
* programmed above.
|
||||
|
|
@ -3219,7 +3165,7 @@ static void stm32serial_dmareenable(struct stm32_serial_s *priv)
|
|||
* in and DMA transfer is stopped.
|
||||
*/
|
||||
|
||||
stm32h5_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
stm32_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, false);
|
||||
}
|
||||
else
|
||||
|
|
@ -3230,7 +3176,7 @@ static void stm32serial_dmareenable(struct stm32_serial_s *priv)
|
|||
* worth of time to claim bytes before they are overwritten.
|
||||
*/
|
||||
|
||||
stm32h5_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
stm32_dmastart(priv->rxdma, stm32serial_dmarxcallback,
|
||||
(void *)priv, true);
|
||||
}
|
||||
|
||||
|
|
@ -3461,50 +3407,57 @@ static bool stm32serial_txready(struct uart_dev_s *dev)
|
|||
* Name: stm32serial_dmarxcallback
|
||||
*
|
||||
* Description:
|
||||
* This function checks the current DMA state and calls the generic
|
||||
* serial stack when bytes appear to be available.
|
||||
* DMA callback for STM32H5 USART RX. Called on half and full‐transfer
|
||||
* events. Reads and clears the GPDMA status flags, notifies the NuttX
|
||||
* serial core of newly arrived bytes, signals end‐of‐buffer when a
|
||||
* full transfer completes, handles RTS flow control restart, and
|
||||
* clears any lingering UART error flags to keep RX‐DMA running.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle returned by stm32_dmachannel()
|
||||
* status - Raw status byte passed by the DMA ISR (ignored here)
|
||||
* arg - Pointer to the STM32 serial driver state
|
||||
* (struct stm32_serial_s)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef SERIAL_HAVE_DMA
|
||||
static void stm32serial_dmarxcallback(DMA_HANDLE handle, uint8_t status,
|
||||
void *arg)
|
||||
static void stm32serial_dmarxcallback(DMA_HANDLE handle,
|
||||
uint8_t status,
|
||||
void *arg)
|
||||
{
|
||||
struct stm32_serial_s *priv = (struct stm32_serial_s *)arg;
|
||||
struct stm32_serial_s *priv = arg;
|
||||
|
||||
if (priv->rxenable && stm32serial_dmarxavailable(&priv->dev))
|
||||
{
|
||||
uart_recvchars(&priv->dev);
|
||||
/* pull whatever is in the buffer now */
|
||||
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
if (priv->iflow)
|
||||
{
|
||||
/* Re-enable RX DMA. */
|
||||
uart_recvchars(&priv->dev);
|
||||
|
||||
stm32serial_dmaiflowrestart(priv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get the masked USART status word to check and clear error flags.
|
||||
*
|
||||
* When wake-up from low power mode was not fast enough, UART is resumed
|
||||
* too late and sometimes exactly when character was coming over UART,
|
||||
* resulting to frame error.
|
||||
* If error flag is not cleared, Rx DMA will be stuck. Clearing errors
|
||||
* will release Rx DMA.
|
||||
/* If it really was a full‑buffer event, signal “done” so the
|
||||
* serial core can rearm/restart the DMA behind the scenes:
|
||||
*/
|
||||
|
||||
priv->sr = stm32serial_getreg(priv, STM32_USART_ISR_OFFSET);
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
/* If you had paused the DMA on RTS flow control, restart it now */
|
||||
|
||||
if ((priv->sr & (USART_ISR_ORE | USART_ISR_NF | USART_ISR_FE)) != 0)
|
||||
if (priv->iflow)
|
||||
{
|
||||
stm32serial_dmaiflowrestart(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clear any USART framing/overrun errors so RX‑DMA
|
||||
* doesn’t get stuck waiting for the UART to clear them.
|
||||
*/
|
||||
|
||||
priv->sr = getreg32(priv->usartbase + STM32_USART_ISR_OFFSET);
|
||||
if (priv->sr & (USART_ISR_ORE | USART_ISR_NF | USART_ISR_FE))
|
||||
{
|
||||
stm32serial_putreg(priv, STM32_USART_ICR_OFFSET,
|
||||
(USART_ICR_NCF | USART_ICR_ORECF |
|
||||
USART_ICR_FECF));
|
||||
USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32serial_pmnotify
|
||||
|
|
|
|||
|
|
@ -443,8 +443,7 @@
|
|||
defined(CONFIG_UART8_RXDMA) || defined(CONFIG_UART9_RXDMA) || \
|
||||
defined(CONFIG_USART10_RXDMA) || defined(CONFIG_USART11_RXDMA) || \
|
||||
defined(CONFIG_USART12_RXDMA)
|
||||
# define SERIAL_HAVE_DMA 0
|
||||
# warning Serial DMA has not been implemented for STM32H5 chips.
|
||||
# define SERIAL_HAVE_DMA 1
|
||||
#endif
|
||||
|
||||
/* Is DMA used on the console UART? */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue