linux pl011串口简述

本文详细解析了基于Linux Kernel 3.4.39的NanoPi2串口驱动配置与实现细节,包括编译选项、驱动注册流程及amba总线匹配过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于nanopi m2内核3.4.39

串口驱动编译选项

Created with Raphaël 2.3.0 linux Kernel Configuration make menuconfig device drivers character devices serial drivers

nanopi m2 4418中串口驱动的选项如下:

       < > 8250/16550 and compatible serial support                                         
            *** Non-8250 serial port support ***                                             
        < > ARM AMBA PL010 serial port support                                             
        <*> ARM AMBA PL011 serial port support                                              
        [*]   Support for console on AMBA serial port                                        
       < > MAX3100 support                                                                
        < > MAX3107 support                                                                
        < > Support for timberdale UART                                                    
        < > Altera JTAG UART support                                                       
        < > Altera UART support                                                            
        < > SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)                  
        < > Xilinx PS UART support                                                         
        < > Nexell S3C SoC serial port support                                             
        [*]   Serial port 0                                                                
        [ ]     Use DMA                                                                    
        [*]   Serial port 1                                                                
        [ ]     Use DMA                                                                    
        [ ]   Serial port 2                                                                
        [*]   Serial port 3                                                                
        [*]   Serial port 4                                                                
        [ ]   Serial port 5                                                                
        [*] Set this to reduce resume time (PL011) 

使用ls /proc/tty/driver/可以看到所有串口驱动,相应的中断号,mmio,传输的数据字节

root@NanoPi2:~# ls /proc/tty/driver/
ttyAMA  usbserial
root@NanoPi2:~# cat /proc/tty/driver/ttyAMA 
serinfo:1.0 driver revision:
0: uart:PL011 rev3 mmio:0xC00A1000 irq:7 tx:2846 rx:133 RTS|DTR
1: uart:PL011 rev3 mmio:0xC00A0000 irq:6 tx:0 rx:0 DSR|CD
2: uart:PL011 rev3 mmio:0xC00A3000 irq:9 tx:0 rx:0
3: uart:PL011 rev3 mmio:0xC006D000 irq:10 tx:0 rx:0
root@NanoPi2:~# ls /dev/ttyAMA* -l
crw------- 1 root tty     204, 64 Sep 20 04:21 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 65 Sep 20 03:28 /dev/ttyAMA1
crw-rw---- 1 root dialout 204, 66 Sep 20 03:28 /dev/ttyAMA2
crw-rw---- 1 root dialout 204, 67 Sep 20 03:28 /dev/ttyAMA3

4418中一共有5个uart串口,使用了PL011驱动,nanopi中勾选了4 个,其中引出给我们用的有3个,ttyAMA0(调试口),ttyAMA2,ttyAMA3

驱动层次

tty层:uart_register_driver,uart_add_one_port
amba层:提供amba_driver,amba_device的注册实现,
UART层:主要涉及uart_driver,amba_driver,uart_port,uart_ops三个结构体,并调用tty层和amba层的两个函数完成amba_driver,uart_driver和uart_port端口的注册

ARM amba总线驱动

amba_device使用分析
Linux AMBA设备驱动注册过程浅析

内核中专门定义了一类amba_bustype、amba_device、amba_driver。具体定义在内核的/drivers/amba/bus.c中

源码查看

设备驱动文件位置
driver/tty/serial/amba-pl011.c
作用
向系统注册串口驱动

从module_init看起

static int __init pl011_init(void)
{
	int ret;
	ret = uart_register_driver(&amba_reg);
	if (ret == 0) {
		ret = amba_driver_register(&pl011_driver);
		if (ret)
			uart_unregister_driver(&amba_reg);
	}
	return ret;
}
static void __exit pl011_exit(void)
{
	amba_driver_unregister(&pl011_driver);
	uart_unregister_driver(&amba_reg);
}

注册了一个uart_driver和一个amba_driver,两个结构的实例如下

static struct uart_driver amba_reg = {
	.owner			= THIS_MODULE,
	.driver_name		= "ttyAMA",/* /proc/tty/sesial/ttyAMA */
	.dev_name		= "ttyAMA",   /* /dev/ttyAMA */
	.major			= SERIAL_AMBA_MAJOR,  /* /dev/ttyAMAn的节点信息 */
	.minor			= SERIAL_AMBA_MINOR,
	.nr			= UART_NR,
	.cons			= AMBA_CONSOLE,
};
//----------------
static struct amba_id pl011_ids[] = {
	{
		.id	= 0x00041011,
		.mask	= 0x000fffff,
		.data	= &vendor_arm,
	},
	{
		.id	= 0x00380802,
		.mask	= 0x00ffffff,
		.data	= &vendor_st,
	},
	{ 0, 0 },
};
MODULE_DEVICE_TABLE(amba, pl011_ids);
static struct amba_driver pl011_driver = {
	.drv = {
		.name	= "uart-pl011",
	},
	.id_table	= pl011_ids,/*用来匹配设备的,*/
	.probe		= pl011_probe,/*在里面实现了uart_port的注册和uart_ops的赋值*/
	.remove		= pl011_remove,
};

当有设备与此驱动匹配时,就调用pl011_probe函数了,主要就是填充uart_add_one_port,并实现uart_ops

static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{
	struct uart_amba_port *uap;
	...
	uap->port.ops = &amba_pl011_pops;
	...
	ret = uart_add_one_port(&amba_reg, &uap->port);
	...
}

先说下匹配过程,在注册驱动时amba_driver_register函数中有下句

drv->drv.bus = &amba_bustype;//表明将该驱动注册到amba_bus总线上去,由amba_bus中的match方法匹配

同样的在注册设备时,amba_device_register–>amba_device_initialize中

dev->dev.bus = &amba_bustype;//同样将设备注册到amba_bus总线上去,由amba_bus中的match方法匹配

而且,在amba_device_register–>amba_device_add中会如果没设定会自行计算出AMBA设备的ID号


int amba_device_add(struct amba_device *dev, struct resource *parent)
{
	...
	/* Hard-coded primecell ID instead of plug-n-play */
	if (dev->periphid != 0)/*如果在添加设备时自行加了id就不再读取硬件上的ID了*/
		goto skip_probe;
	...
	ret = amba_get_enable_pclk(dev);
	if (ret == 0) {
		u32 pid, cid;
		/*
		 * Read pid and cid based on size of resource
		 * they are located at end of region 在芯片资源的末区域读取ID信息
		 */
		for (pid = 0, i = 0; i < 4; i++)
			pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
				(i * 8);
		for (cid = 0, i = 0; i < 4; i++)
			cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
				(i * 8);

		amba_put_disable_pclk(dev);

		if (cid == AMBA_CID)
			dev->periphid = pid;
		if (!dev->periphid)
			ret = -ENODEV;
	}
	...
}

那么最后就是由amba_bus总线中的match来匹配驱动和设备了。如下,table就是驱动中的amba_id 了

struct bus_type amba_bustype = {
	...
	.match		= amba_match,
	...
};
sequenceDiagram
amba_driver->>amba_bus:amba_driver_register()
amba_device->>amba_bus:amba_device_register()

amba_device--amba_driver:通过ID
amba_driver-->>amba_device:(dev->>periphid & table->>mask) == table->>id
<think>好的,我现在需要帮助用户解决在Linux内核中配置并切换使用PL011 UART驱动程序的问题。首先,我需要回忆一下Linux内核中关于串口驱动的相关知识,特别是PL011驱动的配置步骤。 用户提到他们想将串口驱动切换到PL011驱动PL011是ARM平台常见的UART控制器,由ARM公司开发,通常用于处理串口通信。首先,我需要确认用户的内核版本是否支持PL011驱动。一般来说,较新的内核版本都会包含这个驱动,但可能需要手动启用。 接下来,配置内核的步骤应该是通过make menuconfig或者其他配置工具来调整内核选项。我记得在Device Drivers -> Character devices -> Serial drivers这个路径下可以找到相关的串口驱动配置。用户需要在这里找到ARM AMBA PL011串口支持,并确保其被编译进内核或者作为模块加载。 然后,可能需要修改设备树(Device Tree)来指定使用PL011驱动。设备树在Linux内核中用于描述硬件配置,所以用户需要检查他们的设备树文件(.dts或.dtsi)中是否正确配置了PL011的节点,并且确保状态设置为“okay”。例如,检查是否包含类似这样的节点: ``` serial@9000000 { compatible = "arm,pl011"; status = "okay"; ... }; ``` 另外,启动参数也需要确认,比如内核命令行参数中的console参数是否指向了PL011对应的tty设备,比如ttyAMA0。如果之前使用的是其他串口驱动,比如8250驱动,可能需要调整这个参数。 用户可能还需要禁用之前使用的其他串口驱动,避免冲突。例如,如果之前使用的是8250驱动,可能需要在内核配置中将其禁用,或者通过设备树将其状态设为“disabled”。 编译并更新内核后,用户需要重启系统,并通过dmesg查看内核启动日志,确认PL011驱动是否成功加载,并且串口设备是否正确识别。 现在,我需要验证这些步骤是否正确。根据引用[2],设备树在Linux内核中的处理确实涉及将dtb转换为device_node结构,所以正确配置设备树节点是关键。同时,引用[3]提到的生成文件如kernel.itb可能与内核镜像有关,用户可能需要重新编译内核并生成新的镜像。 可能遇到的问题包括设备树配置错误导致驱动无法匹配,或者内核配置中没有启用PL011驱动。这时候需要检查compatible属性是否正确,以及驱动是否编译进内核。 总结下来,步骤大致是:配置内核启用PL011驱动,调整设备树,更新启动参数,禁用旧驱动,编译并测试。需要确保每一步都正确执行,并验证结果。</think>### 如何在Linux内核中配置并切换使用PL011 UART驱动 #### 1. 确认硬件兼容性 首先需确认硬件平台是否支持PL011 UART控制器。PL011是ARM PrimeCell系列的标准UART接口,常见于基于ARM架构的开发板(如树莓派、QEMU虚拟设备等)。通过设备树或硬件手册可验证是否存在PL011节点,例如: ```dts serial@9000000 { compatible = "arm,pl011"; reg = <0x9000000 0x1000>; interrupts = <0 1 4>; status = "disabled"; }; ``` #### 2. 内核配置 - **进入内核配置界面**: ```bash make menuconfig ``` - **启用驱动**: 导航至以下路径并勾选PL011驱动: ``` Device Drivers -> Character devices -> Serial drivers -> ARM AMBA PL011 Serial Port support ``` 选择`<*>`表示编译进内核,或`<M>`作为可加载模块[^1]。 #### 3. 修改设备树 - **编辑设备树文件**(如`pl011.dtsi`): 将PL011节点状态改为`okay`,并确保`compatible`属性为`"arm,pl011"`: ```dts &uart0 { compatible = "arm,pl011"; status = "okay"; }; ``` - **编译设备树**: ```bash dtc -I dts -O dtb -o pl011.dtb pl011.dts ``` 替换原有dtb文件并重启系统[^2]。 #### 4. 调整启动参数 在引导加载程序(如U-Boot)中,修改内核命令行参数以指定PL011作为控制台: ``` console=ttyAMA0,115200 ``` #### 5. 禁用冲突驱动 若系统原先使用8250串口驱动,需在内核配置中禁用: ``` Device Drivers -> Character devices -> Serial drivers -> 8250/16550 and compatible serial support -> < > ``` #### 6. 验证驱动状态 重启后通过以下命令确认驱动加载情况: ```bash dmesg | grep pl011 # 预期输出:pl011 uart0: PL011 UART driver initialized ls /dev/ttyAMA* # 查看设备节点是否存在 ``` #### 7. 测试串口通信 使用`minicom`或`screen`工具测试串口收发: ```bash screen /dev/ttyAMA0 115200 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值