Skip to content

Serial console

Serial console là cổng UART của board được dùng làm console: bootloader và kernel in log ra đó, và sau khi boot xong, người dùng đăng nhập qua đó. Đây là kênh giao tiếp đầu tiên và tin cậy nhất với một board, vì nó hoạt động trước khi có mạng và không phụ thuộc vào user space. Trang này trình bày theo thứ tự: nối phần cứng, thiết bị serial trên máy host, phần mềm terminal, cấu hình console trong kernel, getty để đăng nhập, và Magic SysRq qua serial.

Kết nối phần cứng

UART trên SoC hoạt động ở mức logic của chân I/O, thường là 3,3 V hoặc 1,8 V. Chuẩn RS-232 dùng mức điện áp khác hẳn, cả dương và âm, nên không được nối trực tiếp chân UART của SoC với cổng RS-232; giữa hai bên phải có chip chuyển mức. Cách thường dùng là một bộ chuyển đổi USB sang UART mức logic (USB-UART) cắm vào máy host. Nhiều evaluation board tích hợp sẵn chip USB-UART, khi đó chỉ cần một cáp USB.

Khi nối bằng bộ chuyển đổi rời:

  • TX của board nối với RX của bộ chuyển đổi, RX của board nối với TX của bộ chuyển đổi.
  • Nối chung GND giữa hai bên.
  • Không nối chân nguồn của bộ chuyển đổi vào board đã có nguồn riêng.
  • Mức logic của bộ chuyển đổi phải khớp với mức I/O của chân UART trên board.

Một số lỗi thường gặp và nguyên nhân:

Triệu chứng Nguyên nhân thường gặp
Không thấy ký tự nào TX và RX nối ngược, chưa nối GND, mở sai thiết bị trên host, boot dừng trước khi UART được khởi tạo
Ký tự rác Sai baudrate trên host, hoặc clock cấp cho UART sai nên baudrate thực tế lệch (xem ps-clk-frequency ở trang Porting Linux lên board tùy biến)
Thấy log nhưng không gõ được Dây RX của board đứt, flow control phần cứng đang bật trên host
Log bị cắt giữa chừng khi reset Bộ chuyển đổi lấy nguồn từ board và mất nguồn cùng board

Thiết bị serial trên host

Trên máy host Linux, bộ chuyển đổi USB-UART xuất hiện dưới một trong hai dạng tên:

  • /dev/ttyUSBn: chip có driver riêng trong nhóm USB serial của kernel (FTDI, Silicon Labs CP210x, WCH CH340).
  • /dev/ttyACMn: thiết bị theo lớp USB CDC ACM, thường gặp ở các debug probe tích hợp USB-UART.

Số thứ tự n phụ thuộc vào thứ tự cắm, nên đổi khi có nhiều bộ chuyển đổi. Udev tạo thêm các đường dẫn ổn định trong /dev/serial/by-id/, đặt tên theo hãng, model và số serial của bộ chuyển đổi, và /dev/serial/by-path/, đặt tên theo cổng USB vật lý [7]. Trong script và cấu hình, nên dùng đường dẫn by-id.

Quy tắc udev mặc định của systemd gán các thiết bị có tên dạng tty[A-Z]*[0-9], gồm ttyS0, ttyUSB0 và ttyACM0, vào nhóm dialout [5]. Người dùng cần thuộc nhóm này để mở cổng serial mà không cần quyền root:

sudo usermod -aG dialout $USER   # có hiệu lực ở phiên đăng nhập sau

Phần mềm terminal

Có nhiều chương trình terminal serial: picocom, tio, minicom, screen. Bảng dưới so sánh hai chương trình gọn và dễ dùng trong script:

Chương trình Mở cổng Thoát Gửi BREAK Ghi log
picocom picocom -b 115200 /dev/ttyUSB0 C-a C-x C-a C-\ Tùy chọn --logfile (-g)
tio tio -b 115200 /dev/ttyUSB0 ctrl-t q ctrl-t b -L, kèm -t để thêm timestamp cho mỗi dòng

Phím lệnh của picocom bắt đầu bằng ký tự escape, mặc định là C-a [6]. Trong tio, ctrl-t ? liệt kê toàn bộ phím lệnh [7]. Ví dụ, mở cổng bằng tio qua đường dẫn ổn định và ghi log có timestamp:

tio -b 115200 -t -L /dev/serial/by-id/usb-FTDI_TTL232R-3V3_XXXXXXXX-if00-port0

Log có timestamp phía host hữu ích khi đo thời gian giữa các giai đoạn boot, kể cả giai đoạn trước khi kernel có timestamp riêng.

Cấu hình console trong kernel

Driver UART dùng làm console phải được build sẵn trong kernel, không phải dạng module [3]. Trên Zynq, driver này là xilinx_uartps, tạo thiết bị ttyPSn.

Tham số console= trên kernel command line chọn thiết bị console, theo dạng console=<thiết bị>,<tùy chọn>. Với cổng serial, tùy chọn có dạng bbbbpnf: baudrate, parity (n, o, e), số bit dữ liệu và flow control (r cho RTS); mặc định là 9600n8 [2][3]. Ví dụ trên Zynq:

console=ttyPS0,115200

Có thể khai báo nhiều console=. Khi mỗi loại thiết bị chỉ xuất hiện một lần, log kernel in ra tất cả các console đã khai báo, và /dev/console gắn với console khai báo cuối cùng [3]. Khi cùng một loại thiết bị được khai báo nhiều lần, quy tắc phức tạp hơn, xem tài liệu serial-console.rst của kernel [3].

Cách đặt command line từ U-Boot hoặc Device Tree xem trang Kernel Command Line. Console sớm (earlycon) và mức log xem trang Log boot và earlycon.

Đăng nhập qua serial console

Log kernel in ra console không có nghĩa là đăng nhập được qua console đó: cần một chương trình getty chạy trên cổng serial để hiện dấu nhắc đăng nhập.

systemd. systemd-getty-generator tự bật serial-getty@.service cho các console kernel đang hoạt động. Vì vậy, với systemd, chỉ cần đặt console= đúng là có cả log kernel và dấu nhắc đăng nhập trên cổng serial [4].

BusyBox init. Getty được khai báo trong /etc/inittab. Trường đầu tiên của mỗi dòng, với BusyBox init, là tên tty điều khiển của tiến trình, không phải một ID như SysV init; trường runlevel bị bỏ qua [8]:

/etc/inittab
ttyPS0::respawn:/sbin/getty -L ttyPS0 115200 vt100

Build system. Thông thường cổng getty được khai báo trong cấu hình build thay vì sửa tay:

Build system Biến cấu hình Ví dụ
Buildroot BR2_TARGET_GENERIC_GETTY_PORT, mặc định là console [9] BR2_TARGET_GENERIC_GETTY_PORT="ttyPS0"
Yocto SERIAL_CONSOLES trong file machine, dạng <baudrate>;<tty> [10] SERIAL_CONSOLES = "115200;ttyPS0"

Với Yocto dùng systemd, recipe systemd-serialgetty tạo service getty cho từng cổng trong SERIAL_CONSOLES. Recipe này chỉ cần khi không dùng systemd-getty-generator, vì generator đã tự sinh getty cho các console đang hoạt động [11].

Vai trò của init và cách viết unit cho systemd xem trang Init system.

Magic SysRq qua serial

Magic SysRq là cơ chế gửi lệnh trực tiếp tới kernel, kể cả khi user space không còn phản hồi, miễn là kernel chưa treo hoàn toàn. Kernel cần bật CONFIG_MAGIC_SYSRQ. File /proc/sys/kernel/sysrq quyết định các nhóm chức năng được phép gọi bằng tổ hợp phím; còn ghi vào /proc/sysrq-trigger thì luôn được phép với người dùng có quyền quản trị [1].

Trên serial console, gửi tín hiệu BREAK rồi bấm phím lệnh trong vòng 5 giây. Gửi BREAK hai lần liên tiếp được hiểu là một BREAK thông thường [1]. Tài liệu kernel mô tả cách này cho cổng serial kiểu PC; với các UART khác, việc hỗ trợ phụ thuộc vào driver và chưa được kiểm chứng riêng cho driver của Zynq trong trang này.

Một số phím lệnh hữu ích khi board có dấu hiệu treo [1]:

Phím Tác dụng
t In danh sách task hiện tại
l In stack backtrace của tất cả CPU đang hoạt động
m In thông tin bộ nhớ
s Đồng bộ các filesystem đang mount
u Remount các filesystem sang chỉ đọc
b Reboot ngay, không đồng bộ và không unmount filesystem

Khi còn shell, có thể thử trực tiếp mà không cần BREAK, ví dụ echo t > /proc/sysrq-trigger.

Liên quan

Tài liệu tham khảo

[1] - Linux Magic System Request Key Hacks - docs.kernel.org

[2] - The kernel's command-line parameters - docs.kernel.org, tham số console

[3] - Linux Serial Console - docs.kernel.org

[4] - systemd-getty-generator - man page trong source tree systemd

[5] - 50-udev-default.rules.in - quy tắc udev mặc định của systemd

[6] - picocom(1) - man page của picocom

[7] - tio - README của tio

[8] - examples/inittab - file inittab mẫu của BusyBox

[9] - system/Config.in - Buildroot

[10] - qemuarm.conf - file machine mẫu trong OpenEmbedded-Core, cú pháp SERIAL_CONSOLES

[11] - systemd-serialgetty.bb - recipe trong OpenEmbedded-Core