You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)

核心问题

  1. 如何在Linux用户态程序中触发UART2的初始化(设置ENABLE位),不使用/dev/mem方式?
  2. 是否只能在Bootloader中设置UART控制器的ENABLE位,Linux下无法操作?

我查阅了amba-pl011.c等驱动代码,但未理解串口设备的相关层级。

内容的提问来源于stack exchange,提问作者김태윤

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 13:08:12