Fixed Length Transmit and Receive - DMA
SoC使用DMA将数据发送到PC终端程序(如PUTTY或UartAssist),DMA将数据从Memory传输到UART TX FIFO外设。
SoC使用DMA接收PC终端输入的数据,GDMA将数据从UART RX FIFO 外设传输到Memory。
一旦DMA传输完成,SoC将缓冲数据发送回PC终端。
在该示例中,PC终端程序必须发送大于等于 UART_TX_GDMA_BUFFER_SIZE
个字节的数据,才会触发DMA中断。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多信息请参考快速入门。
硬件连线
连接P3_0和FT232的RX,P3_1和FT232的TX。
编译和下载
该示例的工程路径如下:
Project file: samples\peripheral\uart\trx_gdma\proj\rtl87x2g\mdk
Project file: samples\peripheral\uart\trx_gdma\proj\rtl87x2g\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
准备阶段
启动 PuTTY 或 UartAssist 等PC终端,连接到使用的COM端口,并进行以下UART设置:
波特率: 115200
8 数据位
1 停止位
无校验
无硬件流控
测试阶段
当EVB启动后,在Debug Analyzer工具内观察如下log。
Start uart tx rx by gdma test!
该示例开始发送
### Uart trx gdma sample\r\n
,观察PC终端上出现的字符串。SoC向PC终端发送29个十六进制数(该示例TX Block size
UART_TX_GDMA_BUFFER_SIZE
设置为29): 10 11 12 … 2C, 观察PC终端上显示这29个十六进制数。在PC终端上输入超过29个字符(该示例RX Block size
UART_RX_GDMA_BUFFER_SIZE
设置为29)。观察PC终端上是否显示相同的字符。
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\samples\peripheral\uart\trx_gdma\proj
源码路径:
sdk\samples\peripheral\uart\trx_gdma\src
该工程的工程文件代码结构如下:
└── Project: output_toggle
└── secure_only_app
└── Device includes startup code
├── startup_rtl.c
└── system_rtl.c
├── CMSIS includes CMSIS header files
├── CMSE Library Non-secure callable lib
├── lib includes all binary symbol files that user application is built on
└── rtl87x2g_io.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl_gdma.c
├── rtl_nvic.c
├── rtl_pinmux.c
├── rtl_rcc.c
└── rtl_uart.c
└── APP includes the ble_peripheral user application implementation
├── io_uart.c
└── main_ns.c
初始化
初始化流程包括了 board_uart_init
和 driver_uart_init
。
board_uart_init
中包含了PAD与PINMUX设置:
配置PAD:设置引脚、PINMUX模式、PowerOn、内部上拉。
配置PINMUX:分配引脚分别为UART3_TX、UART3_RX功能。
driver_uart_init
包含了对uart外设的初始化:
使能PCC时钟源。
设置波特率为115200,校验位为无奇偶校验,停止位为1位,数据长度为8bits。
使能UART DMA传输。
设置UART_TxWaterLevel为1,推荐设置为
GDMA_MSize
。设置UART_RxWaterLevel为1,推荐设置为
GDMA_MSize
。使能UART TX DMA, RX DMA。
RCC_PeriphClockCmd(APBPeriph_UART3, APBPeriph_UART3_CLOCK, ENABLE);
...
UART_InitStruct.UART_Div = BaudRate_Table[BAUD_RATE_115200].div;
UART_InitStruct.UART_Ovsr = BaudRate_Table[BAUD_RATE_115200].ovsr;
UART_InitStruct.UART_OvsrAdj = BaudRate_Table[BAUD_RATE_115200].ovsr_adj;
...
UART_InitStruct.UART_DmaEn = UART_DMA_ENABLE;
UART_InitStruct.UART_TxWaterLevel = 1; /* Better to equal: GDMA_MSize */
UART_InitStruct.UART_RxWaterLevel = 1; /* Better to equal: GDMA_MSize */
UART_InitStruct.UART_TxDmaEn = ENABLE;
UART_InitStruct.UART_RxDmaEn = ENABLE;
执行 UART_SendDataByGDMA
,初始化GDMA发送数据。
使用GDMA通道3。
GDMA传输方向为内存到外设传输。
源端地址设置为
GDMA_SendData_Buffer
,目的端地址设置为(&(UART_DEMO->UART_RBR_THR))
。使能GDMA通道3传输完成中断
GDMA_INT_Transfer
。使能GDMA通道3传输。
GDMA_InitStruct.GDMA_ChannelNum = UART_TX_GDMA_CHANNEL_NUM;
GDMA_InitStruct.GDMA_DIR = GDMA_DIR_MemoryToPeripheral;
...
GDMA_InitStruct.GDMA_SourceAddr = (uint32_t)GDMA_SendData_Buffer;
GDMA_InitStruct.GDMA_DestinationAddr = (uint32_t)(&(UART_DEMO->UART_RBR_THR));
...
GDMA_INTConfig(UART_TX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE);
...
GDMA_Cmd(UART_TX_GDMA_CHANNEL_NUM, ENABLE);
执行 UART_ReceiveDataByGDMA
,初始化GDMA接收数据。
使用GDMA通道4。
GDMA传输方向为外设到内存传输。
源端地址设置为
(&(UART_DEMO->RB_THR))
,目的端地址设置为GDMA_ReceiveData_Buffer
。使能GDMA通道4传输完成中断
GDMA_INT_Transfer
。使能GDMA通道4传输。
GDMA_InitStruct.GDMA_ChannelNum = UART_RX_GDMA_CHANNEL_NUM;
GDMA_InitStruct.GDMA_DIR = GDMA_DIR_PeripheralToMemory;
...
GDMA_InitStruct.GDMA_SourceAddr = (uint32_t)(&(UART_DEMO->UART_RBR_THR));
GDMA_InitStruct.GDMA_DestinationAddr = (uint32_t)GDMA_ReceiveData_Buffer;
...
GDMA_INTConfig(UART_RX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE);
...
GDMA_Cmd(UART_RX_GDMA_CHANNEL_NUM, ENABLE);
功能实现
执行
uart_senddata_continuous
,发送### Uart trx gdma sample ###\r\n
到PC终端。执行
GDMA_Cmd()
即开始GDMA从Memory向UART TX FIFO传输数据,当GDMA传输完成时,会触发GDMA_INT_Transfer
中断,进入中断处理函数UART_TX_GDMA_Handler
。清除GDMA通道3
GDMA_INT_Transfer
中断标志位。打印GDMA传输发送数据完成信息。
GDMA_ClearINTPendingBit(UART_TX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer);
DBG_DIRECT("UART_TX_GDMA_Handler, Data transmission completion!");
在PC终端输入字符,即开始GDMA从UART RX FIFO向Memory传输数据,当输入字符超过29个字符(1 Block)时,触发
GDMA_INT_Transfer
中断,进入中断处理函数UART_RX_GDMA_Handler
。清除GDMA通道1
GDMA_INT_Transfer
中断标志位。执行
uart_senddata_continuous
,将GDMA收到的数据发回PC终端。打印GDMA传输完成信息。
GDMA_ClearINTPendingBit(UART_RX_GDMA_CHANNEL_NUM, GDMA_INT_Transfer);
DBG_DIRECT("UART_RX_GDMA_Handler, Data transmission completion!");
uart_senddata_continuous(UART_DEMO, GDMA_ReceiveData_Buffer, UART_RX_GDMA_BUFFER_SIZE);