Tool/software: SDK-10.00.07.04
When configured with DMA, the serial port of AM62x exhibits lower efficiency in continuous data transmission compared to when not using DMA.
The detailed steps as follows:
1.Configuration in DTS
uart4==>/dev/ttyS6
uart5==>/dev/ttyS7
&main_uart4 {
bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart4_pins_default>;
//dmas = <&main_pktdma 0x4404 0>, <&main_pktdma 0xc404 0>;
//dma-names = "rx", "tx";
};
&main_uart5 {
bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart5_pins_default>;
dmas = <&main_pktdma 0x4405 0>, <&main_pktdma 0xc405 0>;
dma-names = "rx", "tx";
};
2.Test code
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h> //exit()
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <time.h>
#define SEND_PKG_SIZE 10000
#define BUF_SIZE 70
int baudSetOpt(int fd,int nSpeed,int nBits,char nEvent,int nStop);
int main(int argc, char *argv[])
{
int uart_fd = 0;
int baudrate = 0;
//int sendCount = 0;
int sendSize = BUF_SIZE;
int count = 0;
int ret = 0;
int i = 0;
unsigned char wBuf[BUF_SIZE];
for(i = 0; i < BUF_SIZE; i++)
{
wBuf[i] = i & 0xFF;
}
//for(i = 0; i < BUF_SIZE; i++)
//{
// if(i%16 == 0)
// printf("\n");
// printf("%d ", wBuf[i]);
//}
if(argc != 3)
{
printf("param error !\n");
printf("please input: ./main /dev/ttyS7 460800\n");
return -1;
}
baudrate = atoi(argv[2]);
uart_fd = open(argv[1], O_RDWR | O_NONBLOCK);
if(uart_fd < 0)
{
printf("%s open file !\n",argv[1]);
return -1;
}
ret = baudSetOpt(uart_fd, baudrate, 8, 'N', 1);
if(ret == -1)
{
printf("%s set baudrate fail !\n", argv[1]);
return -1;
}
long long int err_sum = 0;
//记录时间戳
unsigned long long int start_time = 0;
time_t get_time = 0;
time(&get_time); //时间
start_time = get_time;
for(i=0; i<SEND_PKG_SIZE; i++)
{
count = 0;
while(sendSize != count)
{
ret = write(uart_fd, &wBuf[count], sendSize-count);
if(ret >= 0)
{
count += ret;
}
else
{
err_sum++;
//printf("ret = %d count = %d \n", ret, count);
usleep(10000); //10ms
//perror("write");
//continue;
}
}
//printf(" count = %d \n", count);
}
time(&get_time); //时间
printf(" error times %lld, elapsed time %lld s\n", err_sum, get_time - start_time);
close(uart_fd);
return 0;
}
int baudSetOpt(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
struct termios newtio;
bzero( &newtio, sizeof( newtio ) );
cfmakeraw(&newtio);
tcflush(fd,TCIFLUSH);
newtio.c_cflag &= ~CRTSCTS; // no stream ctrl
newtio.c_cflag |= CLOCAL | CREAD; /* | CRTSCTS //stream strl*/
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 6:
newtio.c_cflag |= CS6;
break;
case 5:
newtio.c_cflag |= CS5;
break;
default:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'o':
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
// newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E':
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'n':
case 'N':
newtio.c_cflag &= ~PARENB;
break;
default:
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
}
switch( nSpeed )
{
case 300:
cfsetispeed(&newtio, B300);
cfsetospeed(&newtio, B300);
break;
case 600:
cfsetispeed(&newtio, B600);
cfsetospeed(&newtio, B600);
break;
case 1200:
cfsetispeed(&newtio, B1200);
cfsetospeed(&newtio, B1200);
break;
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
{
newtio.c_cflag &= ~CSTOPB;
}
else if ( nStop == 2 )
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 1;
newtio.c_oflag = 0;
newtio.c_lflag |= 0;
newtio.c_oflag &= ~OPOST;
newtio.c_cc[VTIME] = 1; /* unit: 1/10 second. */
newtio.c_cc[VMIN] = 1; /* minimal CHARacters for reading */
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
return -1;
}
return 0;
}
aarch64-oe-linux-gcc -mbranch-protection=standard --sysroot=/opt/arago-2023.10/sysroots/aarch64-oe-linux main.c -o main
3. Test results
Send 700,000 bytes at 460,800bps.
root@am62xx-evm:/mnt/nfs/am62x# ./main /dev/ttyS6 460800
error times 1500, elapsed time 15 s
root@am62xx-evm:/mnt/nfs/am62x# ./main /dev/ttyS7 460800
error times 31604, elapsed time 318 s
error times denotes write fail return -1 times, once write fail, account +1, sleep 10ms, then write again.
The UART using DMA takes longer, please help to analysis.