如何在Linux下启用LX2160A的UART2(非/dev/mem方式)
LX2160ARDB板PL011 UART2用户态初始化问题
我在运行Linux的LX2160ARDB板上尝试通过用户态程序使用UART串口,该板搭载2个基于PL011 UART硬件的串口(UART1、UART2),Linux启动后可找到对应设备节点/dev/ttyAMA0、/dev/ttyAMA1。
基础测试程序与现象
我编写了如下测试程序,通过open()和write()操作设备文件:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> int main( void ) { int fd; int retn; int buf[10] = "write...\n"; /* Open UART */ fd = open( "/dev/ttyAMA1", O_RDWR ); if( fd < 0 ) { perror("Open /dev/ttyAMA1 error!"); exit(-1); } printf("Opening /dev/ttyAMA1 -> success!\n"); /* Write Operation - Tx start */ int i; for( i = 0; i < 10; i++ ) { retn = write( fd, buf, 10 ); if( retn < 0 ) printf("Write() failed... retn=%d\n"); else printf("Write() succeeded! retn=%d\n"); sleep(1); } /* Close UART */ printf("Closing /dev/ttyAMA1\n"); close(fd); return 0; }
通过RS232线缆连接SoC串口与笔记本,用终端模拟器查看信号:操作/dev/ttyAMA0(UART1)时可正常看到write...\n,但操作/dev/ttyAMA1(UART2)时无输出且程序无法终止(两种场景下open()、write()均返回有效值)。
寄存器检查结果
我通过访问/dev/mem查看UART控制寄存器,发现UART2的ENABLE位未置1,而UART1的该位已置1(波特率、数据位相关寄存器也存在同样差异):
... int main( void ) { ... fd = open("/dev/mem", O_RDWR | O_SYNC); ... /* mmap() UART, x can be 1 or 2 */ baseaddr = mmap(0, UARTx_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, UARTx_BASE); if( baseaddr == NULL ) { perror("mmap() error"); exit(-1); } printf("mmap succeeded!\n"); /* set pointer of UART Control Register */ uartcr = ( uint32_t * )( baseaddr + UARTCR_OFFSET ); /* check value of Control Register */ printf("Current UARTCR value: %#010x\n", *( uartcr )); ... } ---------- [RESULT] UART1: Current UARTCR value: 0x00000b01 ( bit[0] is 1 ) UART2: Current UARTCR value: 0x00000300 ( bit[0] is 0 ) UARTCR's bit[0] is UARTEN bit
由于UART1被设为控制台,Bootloader仅初始化了UART1并置ENABLE位,未配置UART2。
已尝试的termios配置
我尝试用termios配置UART2,但仍无法看到Hello World!\n\r输出,终端模拟器(Tera Term)设置为115200波特率、8位数据位、无校验、1位停止位、无硬件流控,测试代码如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <string.h> int main( void ) { int fd, ret; char tx_buf[] = "Hello World!\n\r"; struct termios options; /* open UART */ fd = open( "/dev/ttyAMA1", O_RDWR | O_NOCTTY ); if( fd < 0 ) { printf("ERROR open /dev/ttyAMA1\n"); return -1; } /* configure UART */ tcgetattr( fd, &options ); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cc[VTIME] = 10; options.c_cc[VMIN] = 0; options.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG ); options.c_oflag &= ~OPOST; options.c_iflag &= ~( ICRNL | IXON ); cfsetispeed( &options, B115200 ); cfsetospeed( &options, B115200 ); options.c_cflag |= ( CLOCAL | CREAD ); tcflush( fd, TCIFLUSH ); tcsetattr( fd, TCSANOW, &options ); /* test UART */ int i; for( i = 0; i < 10; i++ ) { ret = write( fd, tx_buf, sizeof(tx_buf) ); if( ret != sizeof(tx_buf) ) printf("ERROR write, ret=%d\n\r", ret); printf("write successfully, ret=%d\n\r", ret); sleep(1); } printf("Tx Test END!\n\r"); /* close UART */ close(fd); return 0; }
(注:原代码中structt为笔误,已修正为struct)
核心问题
- 如何在Linux用户态程序中触发UART2的初始化(设置ENABLE位),不使用
/dev/mem方式? - 是否只能在Bootloader中设置UART控制器的ENABLE位,Linux下无法操作?
我查阅了amba-pl011.c等驱动代码,但未理解串口设备的相关层级。
内容的提问来源于stack exchange,提问作者김태윤
相关产品推荐
相关产品推荐

