usart serial console tty port 关系

文章详细介绍了STM32微控制器如何通过串口与Linux内核进行通信,包括/dev/console和/dev/tty设备节点的用途,以及内核printk和用户态printf如何通过不同的API使用串口。还提到了busybox的microcom工具支持的波特率和串口配置选项。

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

关系
关系2关系图
怎么使用串口


/dev/console : 指向一个 tty 设备 , cmdline 中的 console=xxx,可以是  virtual 终端 , 串口终端, 不可以是网络终端
/dev/tty     : 当前终端 , 可以接入  virtual 终端 , 串口终端, 网络终端
/dev/tty[0-63] : virtual 终端 (液晶显示器的虚拟终端),所谓的vt
			   : 但是最多有 7个tty啊(tty1-tty7)
			   : tty0 等同于 tty1
/dev/ttyS[0-31] : 9针串口终端 (只针对x86,在arm平台,如果是三星,则是 ttySAC[0-31] )
	在2.6以后的内核中,部分三星芯片(例如S3C24x0等)将串口终端设备节点命名为ttySACn。
	TI的Omap系列芯片从2.6.37开始芯片自带的UART设备开始使用专有的的omap-uart驱动,故设备节点命名为ttyOn,
	以区别于使用8250驱动时的设备名“ttySn”

/dev/pts/[0-31] :  伪终端(Pseudo Terminal) 网络通过telnet服务或者sshd服务接入的终端
/dev/ttyprintk :
	如果用户空间的 printf() 和内核空间的 printk() 同时执行,二者的输出会互相干扰,内核为此提供了 /dev/ttyprintk 设备文件,可以将用户空间的信息打印到这个设备中,
	这样用户信息与内核信息就会顺序输出,输出的消息会自带 [U] 前缀。对于没有 /dev/ttyprintk 设备的系统,可以用 /dev/kmsg 代替,只是没有了 [U] 标识,需要用户自己添加前缀。
uart_register_driver(&stm32_usart_driver);

1406 static struct uart_driver stm32_usart_driver = {                                 
1407     .driver_name    = DRIVER_NAME,                                               
1408     .dev_name   = STM32_SERIAL_NAME,                                             
1409     .major      = 0,                                                             
1410     .minor      = 0,                                                             
1411     .nr     = STM32_MAX_PORTS,                                                   
1412     .cons       = &stm32_console,                                          
1413 };

1390 static struct console stm32_console = {                                          
1391     .name       = STM32_SERIAL_NAME,                                             
1392     .device     = uart_console_device,                                           
1393     .write      = stm32_console_write,                                           
1394     .setup      = stm32_console_setup,                                           
1395     .flags      = CON_PRINTBUFFER,                                               
1396     .index      = -1,                                                            
1397     .data       = &stm32_usart_driver,                                           
1398 };


 941 static const struct uart_ops stm32_uart_ops = {                                  
 942     .tx_empty   = stm32_tx_empty,                                                
 943     .set_mctrl  = stm32_set_mctrl,                                               
 944     .get_mctrl  = stm32_get_mctrl,                                               
 945     .stop_tx    = stm32_stop_tx,                                                 
 946     .start_tx   = stm32_start_tx,                                                
 947     .throttle   = stm32_throttle,                                                
 948     .unthrottle = stm32_unthrottle,                                              
 949     .stop_rx    = stm32_stop_rx,                                                 
 950     .enable_ms  = stm32_enable_ms,                                               
 951     .break_ctl  = stm32_break_ctl,                                               
 952     .startup    = stm32_startup,                                                 
 953     .shutdown   = stm32_shutdown,                                                
 954     .set_termios    = stm32_set_termios,                                         
 955     .pm     = stm32_pm,                                                          
 956     .type       = stm32_type,                                                    
 957     .release_port   = stm32_release_port,                                        
 958     .request_port   = stm32_request_port,                                        
 959     .config_port    = stm32_config_port,                                         
 960     .verify_port    = stm32_verify_port,                                         
 961 };

platform_driver_register(&stm32_serial_driver);
stm32_serial_probe
	stm32_init_port(stm32port, pdev);
		struct uart_port *port = &stm32port->port;
		port->iotype    = UPIO_MEM;
		port->ops   = &stm32_uart_ops;
		port->irq = platform_get_irq(pdev, 0);
		port->membase = devm_ioremap_resource(&pdev->dev, res);
		port->mapbase = res->start;
	uart_add_one_port(&stm32_usart_driver, &stm32port->port);

stm32_startup
	request_threaded_irq(port->irq, stm32_interrupt, stm32_threaded_interrupt, IRQF_NO_SUSPEND, name, port);
low level
stm32_console_write
	uart_console_write(port, s, cnt, stm32_console_putchar);
		stm32_console_putchar
			while (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) cpu_relax();
			writel_relaxed(ch, port->membase + ofs->tdr);

stm32_start_tx
	stm32_transmit_chars
		if (stm32_port->tx_ch) stm32_transmit_chars_dma
		else                   stm32_transmit_chars_pio
			while (!uart_circ_empty(xmit)) {
				if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) break;
				writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
			}
			
  1 乍看 之下有两套 底层函数来打印东西                                                                                                                                                                     
  2                                                                                  
  3 这分别对应了 内核态的printk 和 用户态的 printf                                   
  4                                                                                  
  5 console 这套 , 如果是内核态调用 printk 来做的,切指定了这个console=xxx, 则都会调用到 console 的底层函数
  	如果是内核打印,这个console和 tty没关系
  	如果/dev/ttySTM0 恰好是 console ,那么用户态时,console就和tty有关系了 , 即 /dev/console  和 /dev/ttySTM0 的关系
  	console 只能链接到唯一的 tty , 但是 我们 可以在 多个tty上建立交互
  6 stm32_uart_ops 这套,如果用户态调用 write 系统调用来做的,切指定了这个tty(/dev/ttySTMx),则会调用到 stm32_uart_ops的底层函数,
  	这套的上层子系统是 tty
  7                                                                                  
  8                                                                                  
  9                                                                                  
 10                                                                                  
 11 如果 刚好  /dev/ttySTM0 恰好是 console , 则他们就会往同一个串口输出。相当于     
 12 用户态和内核态用不同的API 分时复用这个串口

busybox 支持 microcom , 目前好像支持的波特率有
9600 // 默认 microcom /dev/ttySTM0
19200
38400
57600
115200
230400
460800
921600
1843200 // 开始不支持
3686400
7372800
14745600
29491200
58982400
117964800
235929600
microcom -s 115200 /dev/ttySTM0 // ctrl-x 退出
具体查看 uart_parse_options
console=ttySTM0,115200n8n
ttySTM0 // 串口
115200 波特率 baud rate
n 是否校验 parity
8 数据bit个数 number of data bits
n 是否支持流控 flow control character
<think>嗯,用户问的是“serial port 组件在哪里”。首先,我需要确定用户的具体需求。可能他们在开发嵌入式系统、单片机项目,或者在使用某种开发框架时遇到了问题。常见的场景可能是在Arduino、STM32、Raspberry Pi这样的硬件平台上寻找串口组件的位置或配置方法。 接下来,我得考虑不同的平台情况。比如,Arduino的串口通常通过Serial对象直接调用,而STM32可能涉及HAL库CubeMX配置。树莓派的话,可能涉及到Linux下的设备文件如/dev/ttyS0或/dev/ttyAMA0。用户可能没有明确说明使用的平台,所以需要覆盖多种可能性。 然后,用户可能对硬件连接软件配置不太清楚。比如,是否需要启用特定的引脚作为串口,或者操作系统中如何识别串口设备。对于嵌入式开发,配置时钟GPIO也是关键步骤。此外,有些开发环境如STM32CubeMX需要图形化配置生成代码,用户可能不熟悉这一流程。 还要考虑到用户可能遇到的常见问题,比如权限不足无法访问串口设备,或者波特率配置错误导致通信失败。这时候需要提醒检查权限配置参数。另外,不同操作系统下的设备名称可能不同,比如Windows用COMx,Linux用/dev/tty*,这也需要区分说明。 最后,总结时需要给出清晰的步骤,帮助用户根据他们的具体硬件开发环境定位串口组件,并提供验证方法常见问题解决方案。确保回答结构清晰,分点说明不同情况,让用户能够逐步排查解决问题。</think>关于“串口(Serial Port)组件在哪里”的问题,需要根据具体的使用场景(硬件开发、软件开发、操作系统等)分情况说明: 一、硬件层面 1. 微控制器/单片机(如STM32、Arduino): - 在芯片引脚上查找标有"TX"(发送)/"RX"(接收)的物理引脚 - 例如Arduino Uno的D0(RX)D1(TX) - 需通过数据手册确认具体引脚映射 2. 开发板扩展接口: - 常见于调试接口区域(如ARM Cortex的SWD/JTAG接口旁) - 树莓派的GPIO排针上标有TXD/RXD的引脚(BCM 14/15) 二、软件层面 1. 嵌入式开发环境: - STM32CubeMX:在"Connectivity"分类下选择USART/UART模块 - Arduino IDE:通过`Serial`对象直接调用(自动映射到硬件串口) 2. Linux系统: - 设备文件路径:`/dev/ttyS0` (原生串口), `/dev/ttyUSB0` (USB转串口) - 查看命令:`ls /dev/tty*` 或 `dmesg | grep tty` 3. Windows系统: - 设备管理器 → 端口(COMLPT) → 显示为"USB Serial Port (COMx)" - 需要安装对应驱动(如CH340、CP2102等) 三、配置验证方法 1. 硬件连接验证: - 使用USB转TTL模块时,注意交叉连接(设备TX接模块RX,设备RX接模块TX) - 测量电压:TTL电平应为3.3V/5V,RS232电平为±12V 2. 软件通信测试: ```cpp // Arduino示例 void setup() { Serial.begin(9600); // 初始化串口 } void loop() { Serial.println("Hello Serial"); delay(1000); } ``` 四、常见问题排查 1. 权限问题(Linux/Mac): - 执行 `sudo usermod -a -G dialout $USER` 后重启 2. 端口冲突: - 关闭其他占用串口的程序(如Arduino IDE自带的串口监视器) 3. 波特率不匹配: - 需确保收发双方使用相同波特率(9600/115200等) 请根据实际使用场景确认具体位置。如果是特定开发板或芯片型号,提供更多细节可获得更精确的定位说明。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值