UART的默认波特率

又是一年没更新了,这一年多真够忙碌的。刚开始这个项目人数不够,各种新 feature 移植,各个模块问题都得解决,各种救火,自己都没有好好沉下来深入的看代码,而结果却是吃力并不讨好。现在人数招聘够了,自己终于可以专心下来安安静静的做一个小程序员,写代码,解bug, 了解新技术,及时充电,及时记录。

开始记录,平台 :mdm9x07

刚开始以为 UART 的波特率会在dts里面配置,结果没找到,虽然在终端可以通过 stty去配置,但stty -a 里面默认的波特率从哪来的呢?

于是去看了看源码。

int uart_register_driver(struct uart_driver *drv)
	normal = alloc_tty_driver(drv->nr);				
	drv->tty_driver = normal;			--- 分配一个 tty_driver ,并将drv->tty_driver 指向它
	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	---B0 设置 初始波特率 等,B9600 即0x0000000d
	tty_set_operations(normal, &uart_ops);		--- driver->ops = op; 将 tty 的 ops 定位到 uart 的 ops 
	tty_port_init(port);
	port->ops = &uart_port_ops;
	tty_register_driver(normal);
这个函数里面 normal->init_termios.c_cflag 这里定义了波特率 9600,即是默认波特率。那么它是怎么传递的并最终配置UART 寄存器生效的呢?

继续 看 tty_register_driver

int tty_register_driver(struct tty_driver *driver)
	register_chrdev_region(dev, driver->num, driver->name);	--- 注册字符设备
	list_add(&driver->tty_drivers, &tty_drivers);		--- 将 driver->tty_drivers 加入到全局变量 tty_drivers
然后呢?会发现在 uart_change_speed 函数中调用了 uport->ops->set_termios去设置,但是还想了解在 uart_change_speed之前的过程是如何传递的。

用 dump_stack() 打出 uart_open 的调用栈:

uart_open
tty_open
chrdev_open 
do_dentry_open
do_last.isra.32
path_openat 
do_filp_open
do_sys_open 
那么从 tty_open 开始看起:

static int tty_open(struct inode *inode, struct file *filp)
	tty_lookup_driver(device, filp, &noctty, &index);	--> get_tty_driver --> list_for_each_entry(p, &tty_drivers, tty_drivers) 
	tty_init_dev(driver, index);				--- 与 B1 相关
	tty->ops->open(tty, filp);			        --- 即 uart_open
tty_register_driver 把 driver->tty_drivers 放入链表 tty_drivers,这里又把它取出来了。

tty_init_dev 这个函数就把 uart_register_driver函数中定义的init_termios传递到 tty->termios 这里来了:

tty_init_termios	<-- tty_standard_install  <-- tty_driver_install_tty <-- tty_init_dev
tty_reset_termios	<-- tty_ldisc_hangup      <-- __tty_hangup         <-- do_tty_hangup  <-- alloc_tty_struct  <-- tty_init_dev
	tty->termios = tty->driver->init_termios;
为什么tty->ops->open 对应的是 uart_open?

上面的uart_register_driver里面有tty_set_operations,即 driver->ops = op; 将 tty 的 ops 定位到 uart 的 ops,这样 tty->ops->open 就对应的是uart_open。

static const struct tty_operations uart_ops = {
	.open		= uart_open,
...
};
现在开始看 uart_open。

static int uart_open(struct tty_struct *tty, struct file *filp)
	uart_startup(tty, state, 0);
		uart_port_startup(tty, state, init_hw);
来到 uart_port_startup:

static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,int init_hw)
	uport->ops->startup(uport);			--- 已知 uport->ops = &msm_hs_ops;即 msm_hs_startup(uport)
	uart_change_speed(tty, state, NULL);	
其中 uport->ops->startup 指向 msm_hs_startup,负责一些初始化工作,比如使能 uart clk,irq, uart pin,写各种寄存器。

为什么 uport->ops->startup 指向 msm_hs_startup? 因为在 msm_hs_probe 有 uport->ops = &msm_hs_ops;uart_add_one_port(&msm_hs_driver, uport);其中 msm_hs_ops 结构体中有.startup = msm_hs_startup。

继续看uart_change_speed,根据termios = &tty->termios;即可联系前面的B0,B1语句,知道波特率信息已经传入 termios 中

static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,struct ktermios *old_termios)	
	termios = &tty->termios;				--- 与 B0, B1 相关,得到 termios 信息
	uport->ops->set_termios(uport, termios, old_termios);	--- 即 msm_hs_set_termios

接着 uport->ops->set_termios 指向 msm_hs_set_termios:

static void msm_hs_set_termios(struct uart_port *uport,struct ktermios *termios,struct ktermios *oldtermios)
	bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);		--- C1.1	
	msm_hs_set_bps_locked(uport, bps);						--- C1.2
在这个函数中,uart_get_baud_rate 根据 termios->c_cflag 的信息从baud_table取出对应波特率 9600.

uart_get_baud_rate
	baud = tty_termios_baud_rate(termios);

speed_t tty_termios_baud_rate(struct ktermios *termios)
	cbaud = termios->c_cflag & CBAUD;		--- CBAUD 为 0x0000100f, 即保留 c_cflag 的0~3,12 几个bit位
	if (cbaud < 1 || cbaud + 15 > n_baud_table)
		termios->c_cflag &= ~CBAUDEX;		--- CBAUDEX 为 0x00001000, 即把 bit12置零,最终保留 c_cflag 的0~3bit位
	else
		cbaud += 15;	
	return baud_table[cbaud];
	
static const speed_t baud_table[] = {
	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
9600, 19200, 38400, 57600, 115200, 230400, 460800, ...}
baud_table[13] = 96000,而 msm_hs_set_termios 中msm_hs_set_bps_locked 则是根据波特率配置 UART 的寄存器:

static void msm_hs_set_bps_locked(struct uart_port *uport,unsigned int bps)
	case 9600:
	msm_hs_write(uport, UART_DM_CSR, 0x55);

     if (bps > 460800) {
        uport->uartclk = bps * 16;
        if (bps == 4000000)
            uport->uartclk = BLSP_UART_CLK_FMAX;
     } else {
        uport->uartclk = 7372800;
     }
uport->uartclk 默认值 是7372800,根据datasheet上UART_DM_CSR寄存器的分频规则如下:

0xF = 16
0xE = 32
0xD = 48
0xC = 64
0xB = 96
0xA = 128
0x9 = 192
0x8 = 256
0x7 = 384
0x6 = 512
0x5 = 768
0x4 = 1536
0x3 = 3072
0x2 = 6144
0x1 = 12288
0x0 = 24576

那么msm_hs_write(uport, UART_DM_CSR, 0x55);,即按照 768 分频,7372800/768=9600.

当然如果想把UART 默认波特率改成115200呢?

很简单,在uart_register_driver中把 normal->init_termios.c_cflag改成:

normal->init_termios.c_cflag = B1152000 | CS8 | CREAD | HUPCL | CLOCAL;    

而 B115200为0x00001002,即.c_cflag 0~3bit位十进制值为2,那么在tty_termios_baud_rate中会cbaud += 15后  cbaud为17,结果baud_table[17] = 115200;在msm_hs_set_bps_locked中有case 115200: msm_hs_write(uport, UART_DM_CSR, 0xcc); 而uport->uartclk = 7372800;0xc的分频系数为 64,那么7372800/64=115200.


推荐两个博客,里面有关于uart的分析,还有清晰的图片:

http://blog.csdn.net/lizuobin2/article/details/51773305

http://www.cnblogs.com/aaronLinux/p/5616153.html







  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Raspberry Pi 4B的波特率是根据使用的串口或者通信协议而定的。Raspberry Pi 4B有多个可用的UART串口,每个串口都可以设置不同的波特率。对于UART串口,可以通过设置config.txt文件或者使用软件来配置不同的波特率,常见的波特率有9600、115200等。 另外,对于其他通信协议,如SPI和I2C,Raspberry Pi 4B也支持不同的通信速率,这些通信速率也可以被认为是一种波特率。SPI通信速率可以在代码中进行配置,一般在MHz级别。I2C通信速率也可以通过代码进行配置,一般在100kHz或400kHz。 需要注意的是,波特率是指单位时间内传输的比特数,波特率越高,传输速率越快,但也会引入更多的噪声和误码。因此,在选择和配置波特率时,需要根据实际应用场景的需求进行权衡,确保数据传输的稳定性和准确性。 总之,Raspberry Pi 4B的波特率取决于所使用的串口或通信协议,并且可以通过软件或代码进行配置。根据不同的需求和应用场景,选择合适的波特率可以实现稳定和快速的数据传输。 ### 回答2: Raspberry Pi 4B的波特率是指用于与其他设备进行通信的传输速率。波特率是指在单位时间内传输的数据位数。Raspberry Pi 4B支持多种不同的波特率,可以根据需要进行设置。 Raspberry Pi 4B的默认波特率是115200,这是一个常用的标准波特率,可用于与其他硬件设备进行串口通信。可以通过设置串口配置文件或者命令行界面来修改默认波特率。 除了默认波特率外,Raspberry Pi 4B还支持更高的波特率,如230400、460800、921600等。这些更高的波特率可以用于需要快速数据传输的应用,例如高速传输大量数据或者与其他高速设备进行通信。 修改Raspberry Pi 4B的波特率可以通过修改配置文件来实现,如修改串口配置文件中的波特率参数。另外,也可以通过命令行界面使用特定的指令来修改波特率设置。在修改波特率之后,需要确保与Raspberry Pi 4B通信的设备也能支持相同的波特率,以保证正常的数据传输。 总之,Raspberry Pi 4B的波特率是可以根据需求进行修改的,它可以支持多种不同的波特率用于与其他设备进行通信。根据实际应用的需要选择合适的波特率可以确保数据的快速、稳定传输。 ### 回答3: Raspberry Pi 4B支持的常用串口通信波特率是300字。 Raspberry Pi 4B在硬件上增加了两个串口UART接口,其中一个UART接口可通过GPIO引脚使用,另一个UART可通过USB-C接口使用。这两个UART接口都可以用于与外部设备进行串口通信。 在Raspberry Pi上,设定波特率通常需要在操作系统中进行配置。对于GPIO UART接口,可以通过在命令行中使用"stty"命令来设定波特率。通过设置特定的参数,比如"-F /dev/serial0"来指定使用的串口设备,并通过参数"-speed 300"来设置波特率为300。 对于USB-C UART接口,通常可以在操作系统的串口设置菜单中设定波特率。支持的波特率通常包括300、1200、2400等常见的波特率。用户可以根据实际需要选择适合的波特率。 总而言之,Raspberry Pi 4B支持的波特率包括300字,用户可以根据实际需求选择适合的波特率来与外部设备进行串口通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值