In embedded systems, the serial port can be used to output logs for system debugging, and can also be used for short-distance low-speed communication. It is a very practical communication port.
This article introduces functions based on the single-board kernel.RockPI 4A
Linux 4.4
RK3399 UART
1. Introduction to UART
UART(Universal Asynchronous Receiver/Transmitter)
: Universal asynchronous receiver-transmitter, suitable for short-distance, low-speed, serial and full-duplex data transmission.
In China, the serial port generally refers to the serial communication port. There are 9 pins, using levels.PC
COM
RS-232
In embedded systems, serial port generally refers to port. Generally, 3 pins are used and levels are used.UART
TTL
TTL/RS-232/RS-485
Refers to the level standard, the difference is as follows:
level standard | logic 0 | Logic 1 | transfer method |
---|---|---|---|
TTL level |
0 ~ 0.4V |
2.4 ~ 5V |
full duplex |
RS-232 level |
3 ~ 15V |
-15 ~ -3V |
full duplex |
RS-485 level |
-6 ~ -2V |
2 ~ 6V |
Half-duplex (differential transmission, longer distance) |
When debugging the embedded single board, you can select the module to implement serial communication with the single board, as shown in the figure below:USB转TTL
PC
RK3399 UART
Controller features:
1. Support 5-way serial port.
2. Support or interrupt transmission mode.DMA
3. Supports two 64-byte sending and receiving .FIFO
4. Support 5/6/7/8 serial data sending or receiving.bit
5. Supports standard asynchronous communication bits such as start, stop and parity check.
6. The maximum clock baud rate can be supported up to 4.Mbps
7. Support automatic flow control mode.UART0/3
RK3399 UART
The pin description is shown in the figure below:
2. UART connection
ROCKPi 4A
The board has a 40-pin expansion port, as shown in the picture below:radxa
RockPI 4A
The single board is used as a debugging serial port, and the pin connection method for converting to a serial port is as follows:UART2
USB
TTL
RockPI4A single board | USB to TTL serial port |
---|---|
PIN8(UART2_TXD) | RXD |
PIN9(GND) | GND |
PIN10(UART2_RXD) | TXD |
RockPI 4A
The debugging serial port configuration of the single board is shown in the figure below:
When connecting the serial port, you must first ensure that the connection is correct, and then check whether the serial port pin levels are compatible and whether the serial port parameter configuration is correct. Otherwise, the serial port may be unavailable or garbled.GND
3. UART configuration
Take a single board as an example to configure the configuration in the introduction .ROCKPI 4A
RK3399 DTS
UART
3.1. Serial port alias
Ordinary serial port devices will be numbered according to the serial port number and will be registered as the corresponding device.dts
aliases
serialx
ttySx
Configuration file: .arch/arm64/boot/dts/rockchip/rk3399.dtsi
RK3399 DTS
is defined as follows :aliases
aliases { ... serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; serial3 = &uart3; serial4 = &uart4; };
If you register the modification as , you can make the following modifications:UART4
ttyS1
aliases { ... serial0 = &uart0; serial1 = &uart4; ## Use uart4 to replace uart1 ... serial4 = &uart1; };
3.2. Serial port configuration
Configuration file: .arch/arm64/boot/dts/rockchip/rk3399.dtsi
UART0 dts
The configuration is as follows:
uart0: serial@ff180000 { compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; reg = <0x0 0xff180000 0x0 0x100>; ## uart0 register address 0xff180000 and mapping size 0x100 clocks = <&cru SCLK_UART0 >, <&cru PCLK_UART0>; ## The clock used by uart0 clock-names = "baudclk", "apb_pclk"; interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>; ## uart0 uses SPI interrupt, interrupt number 131 (99+32), DMA mode is not used reg-shift = <2>; ## The register address is offset by 2 bits, that is, offset+4 reg-io-width = <4>; ## The register bit width is 32 bits. pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; ## uart0 uses the flow control pin status = "disabled"; ## Default off state };
UART0 pinmux
configuration, including flow control pins .cts/rts
uart0 { uart0_xfer: uart0-xfer { rockchip,pins = <2 16 RK_FUNC_1 &pcfg_pull_up>, <2 17 RK_FUNC_1 &pcfg_pull_none>; }; uart0_cts: uart0-cts { rockchip,pins = <2 18 RK_FUNC_1 &pcfg_pull_none>; }; uart0_rts: uart0-rts { rockchip,pins = <2 19 RK_FUNC_1 &pcfg_pull_none>; }; };
Note:
RK3399 UART0
The interrupt number is 131. The interrupt number starts from 32, and the interrupt number in starts from 0 by default, so the configured interrupt number is: 131-32, which is 99.SPI
dts
SPI
UART0
After the system starts, you can view the serial port interrupts (131 and 132):
root@xiaotianbsp:/# cat proc/interrupts CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 14: 0 0 0 0 0 0 GICv3 29 Edge arch_timer ... 35: 16 0 0 0 0 0 GICv3 131 Level serial ... 222: 301 0 0 0 0 0 GICv3 132 Level debug ... Err: 0
3.3. Serial port enablement
Configuration file: .arch/arm64/boot/dts/rockchip/rockpi-4-linux.dtsi
UART0 dts
The enabling configuration is as follows:
&uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer &uart0_cts>; status = "okay"; ## okay: turn on the serial port function; disabled: turn off the serial port function. }; & uart2 { status = "okay"; ## Enable serial port 2 };
Note:
status = "okay"
or , but cannot be used ."ok"
enable
The kernel parsing code is as follows:
static bool __of_device_is_available(const struct device_node *device) { ... status = __of_get_property(device, "status", &statlen); ... if (statlen > 0) { if (!strcmp(status, "okay") || !strcmp(status, "ok")) return true; } return false; }
3.4、ttyFIQ0
The system is used as a device./dev/ttyFIQ0
console
Configuration file: , the content is as follows:arch/arm64/boot/dts/rockchip/rockpi-4-linux.dtsi
fiq_debugger: fiq-debugger { status = "disabled"; compatible = "rockchip,fiq-debugger"; rockchip,serial-id = <2>; ## Use the serial port number (UART2), modify the value of this attribute, and switch the serial port. Switch the pinmux of the serial port at the same time rockchip,signal-irq = <182>; rockchip,wake-irq = <0>; rockchip,irq-mode-enable = <1>; /* If enable uart uses irq instead of fiq */ rockchip ,baudrate = <1500000>; /* Only 115200 and 1500000 */ pinctrl-names = "default"; pinctrl-0 = <&uart2c_xfer>; ## pinmux must correspond to serial-id };
RockPI 4A
For the system used by the board , set the parameters in the configuration file.Debian
extlinux.conf
console
root@xiaotianbsp:/boot/extlinux# cat extlinux.conf timeout 10 menu title select kernel label kernel-4.4.154-90-rockchip-ga14f6502e045 kernel /vmlinuz-4.4.154-90-rockchip-ga14f6502e045 devicetreedir /dtbs/4.4 .154-90-rockchip-ga14f6502e045 ## Enable early printk, ttyFIQ0 is used as the console device, the serial port baud rate is 1.5M, 8 data bits, 1 stop bit append earlyprintk console=ttyFIQ0,1500000n8 init=/sbin/init root=PARTUUID=b921b045-1d rw rootwait rootfstype=ext4
After the system starts, you can view it through.cmdline
root@xiaotianbsp:~# cat /proc/cmdline earlyprintk console=ttyFIQ0,1500000n8 init=/sbin/init root=PARTUUID=b921b045-1d rw rootwait rootfstype=ext4
4. UART driver
RK3399 Linux4.4
The kernel driver uses the 8250 universal driver, the type is . Main implementation files:UART
16550A
drivers/tty/serial/8250/8250_dma.c ## UART dma implementation drivers/tty/serial/8250/8250_dw.c ## Synopsys DesignWare 8250 serial port driver drivers/tty/serial/8250/8250_early.c ## early console implementation drivers/tty/serial/8250/8250_port.c ## Related interfaces for UART port configuration
UART
Drivers and debugging will be introduced later.
5. Kernel log debugging
In embedded systems, the most common thing is to use the serial port to output kernel logs for functional debugging.Linux
5.1、printk
In the kernel, functions are available to output kernel information to the kernel information buffer.Linux
printk()
Kernel log output is divided into different levels, definition file: , including:include/linux/kern_levels.h
#define LOGLEVEL_EMERG 0 /* system is unusable */ #define LOGLEVEL_ALERT 1 /* action must be taken immediately */ #define LOGLEVEL_CRIT 2 /* critical conditions */ #define LOGLEVEL_ERR 3 /* error conditions */ #define LOGLEVEL_WARNING 4 /* warning conditions */ #define LOGLEVEL_NOTICE 5 /* normal but significant condition */ #define LOGLEVEL_INFO 6 /* informational */ #define LOGLEVEL_DEBUG 7 /* debug-level messages */
In addition to functions, you can also use and .printk()
pr_**()
dev_**()
pr_**
Definition file: , the macro is defined as follows:include/linux/printk.h
#define pr_emerg(fmt, ...) \ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert(fmt, ...) \ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) #define pr_crit(fmt, ...) \ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) #define pr_err(fmt, ...) \ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
dev_**
Definition file: , the function is defined as follows:drivers/base/core.c
#define define_dev_printk_level(func, kern_level) \ void func(const struct device *dev, const char *fmt, ...) \ { \ struct va_format vaf; \ va_list args; \ \ va_start(args, fmt); \ \ vaf.fmt = fmt; \ vaf.va = &args; \ \ __dev_printk(kern_level, dev, &vaf); \ \ va_end(args); \ } \ EXPORT_SYMBOL(func); define_dev_printk_level(dev_emerg, KERN_EMERG); define_dev_printk_level(dev_alert, KERN_ALERT); define_dev_printk_level(dev_crit, KERN_CRIT); define_dev_printk_level(dev_err, KERN_ERR); define_dev_printk_level(dev_warn, KERN_WARNING); define_dev_printk_level(dev_notice, KERN_NOTICE); define_dev_printk_level(_dev_info, KERN_INFO);
5.1.1. Log output level
The kernel log output level can be adjusted by modifying the value of or .loglevel
/proc/sys/kernel/printk
Before the system starts, you can adjust the serial port log output through configuration.loglevel
root@xiaotianbsp:~# cat /boot/extlinux/extlinux.conf ... label kernel-debug kernel /debug/Image fdt /debug/rk3399-rock-pi-4a.dtb ## Modify loglevel to adjust the serial port output log level append earlyprintk console=ttyFIQ0,1500000n8 loglevel=4 init=/sbin/init root=PARTUUID=b921b045-1d rw rootwait rootfstype=ext4 no_console_suspend initcall_debug
Other systems (such as: or ) are generally modified in .Ubuntun、Buildroot
Android
bootargs
loglevel
Note:
no_console_suspend
Used for Linux system power management debugging, which means that after the system sleeps (suspend), the serial port does not sleep and can still output.
After the system is started, the serial port log output level can also be dynamically adjusted.
root@xiaotianbsp:/proc/sys/kernel# cat printk 7 4 1 7 root@xiaotianbsp:/proc/sys/kernel# echo 4 > printk root@xiaotianbsp:/proc/sys/kernel# cat printk 4 4 1 7
printk
The numbers in correspond to different log levels. Just modify the log level of the port.console
int console_printk[4] = { CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ ## Console log level MESSAGE_LOGLEVEL_DEFAULT, /* default_message_loglevel */ ## Default message log level CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */ ## Minimum console log level CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ ##Default console log level };
5.1.2. Log timestamp
After the system starts, the display of kernel log timestamps can be dynamically adjusted.
## 1. The time value is Y, which means the timestamp root@xiaotianbsp:/# cat /sys/module/printk/parameters/time Y ## 2. At this time, the log shows a timestamp root@xiaotianbsp:/# find . -name time [ 1719.836194] FAT-fs (sda4): error, invalid access to FAT (entry 0x07b03538) [ 1719.836874] FAT-fs (sda4): error, invalid access to FAT (entry 0x07b03538) ## 3. Set the time value is N root@xiaotianbsp:/# echo N > /sys/module/printk/parameters/time ## 4. At this time, the log shows a timestamp root@xiaotianbsp:/# find . -name time FAT-fs (sda4): error, invalid access to FAT (entry 0x07b03538) FAT-fs (sda4): error, invalid access to FAT (entry 0x07b03538)
5.2、dmesg
After the system starts, if you have missed the kernel startup phase or use a non-serial port (for example: login) to connect the debugging board, you can use to view the kernel log.adb/ssh
dmesg
dmesg
Usage is as follows:
root@xiaotianbsp:/# dmesg -h Usage: dmesg [options] Display or control the kernel ring buffer. Options: -C, --clear clear the kernel ring buffer -c, --read-clear read and clear all messages -D, --console-off disable printing messages to console -E, --console-on enable printing messages to console -F, --file <file> use the file instead of the kernel log buffer -f, --facility <list> restrict output to defined facilities -H, --human human readable output -k, --kernel display kernel messages -L, --color[=<when>] colorize messages (auto, always or never) colors are enabled by default -l, --level <list> restrict output to defined levels -n, --console-level <level> set level of messages printed to console -P, --nopager do not pipe output into a pager -r, --raw print the raw message buffer -S, --syslog force to use syslog(2) rather than /dev/kmsg -s, --buffer-size <size> buffer size to query the kernel ring buffer -u, --userspace display userspace messages -w, --follow wait for new messages -x, --decode decode facility and level to readable string -d, --show-delta show time delta between printed messages -e, --reltime show local time and time delta in readable format -T, --ctime show human-readable timestamp (may be inaccurate!) -t, --notime don't show any timestamp with messages --time-format <format> show timestamp using the given format: [delta|reltime|ctime|notime|iso] Suspending/resume will make ctime and iso timestamps inaccurate. -h, --help display this help and exit -V, --version output version information and exit Supported log facilities: kern - kernel messages user - random user-level messages mail - mail system daemon - system daemons auth - security/authorization messages syslog - messages generated internally by syslogd lpr - line printer subsystem news - network news subsystem Supported log levels (priorities): emerg - system is unusable alert - action must be taken immediately crit - critical conditions err - error conditions warn - warning conditions notice - normal but significant condition info - informational debug - debug-level messages For more details see dmesg(1).
5.2.1. Display kernel logs
root@xiaotianbsp:/# dmesg [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Initializing cgroup subsys cpuset [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Initializing cgroup subsys cpuacct [ 0.000000] Linux version 4.4.154-90-rockchip-ga14f6502e045 (root@2705a206000b) (gcc version 7.3.1 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701] (Linaro GCC 7.3-2018.05) ) #22 SMP Tue Jul 30 10:32:28 UTC 2019
5.2.2. Limit log output level
## 仅输出error信息 root@xiaotianbsp:/# dmesg -l err [ 2.170152] rockchip-pcie f8000000.pcie: PCIe link training gen1 timeout! [ 2.175658] rk-vcodec ff650000.vpu_service: could not find power_model node [ 2.180010] rk-vcodec ff660000.rkvdec: could not find power_model node [ 2.200359] rockchip-vop ff900000.vop: missing rockchip,grf property [ 2.201913] rockchip-vop ff8f0000.vop: missing rockchip,grf property [ 2.203632] i2c i2c-9: of_i2c: modalias failure on /hdmi@ff940000/ports [ 2.240381] mali ff9a0000.gpu: Failed to get regulator [ 2.240839] mali ff9a0000.gpu: Power control initialization failed [ 2.260317] rk_gmac-dwmac fe300000.ethernet: cannot get clock clk_mac_speed
## 同时输出error和warning信息 root@xiaotianbsp:/# dmesg -l err,warn [ 0.000000] rockchip_clk_register_frac_branch: could not find dclk_vop0_frac as parent of dclk_vop0, rate changes may not work [ 0.000000] rockchip_clk_register_frac_branch: could not find dclk_vop1_frac as parent of dclk_vop1, rate changes may not work [ 0.000000] rockchip_cpuclk_pre_rate_change: limiting alt-divider 33 to 31 [ 1.589058] thermal thermal_zone1: power_allocator: sustainable_power will be estimated [ 1.637902] phy phy-ff770000.syscon:[email protected]: Failed to get VBUS supply regulator [ 1.639962] phy phy-ff770000.syscon:[email protected]: Failed to get VBUS supply regulator [ 2.170152] rockchip-pcie f8000000.pcie: PCIe link training gen1 timeout!
5.2.3. Search for a certain piece of information
root@xiaotianbsp:~# dmesg | grep rockchip-vop [ 2.197270] rockchip-vop ff900000.vop: missing rockchip,grf property [ 2.198853] rockchip-vop ff8f0000.vop: missing rockchip,grf property root@xiaotianbsp:~# dmesg | grep xiaotianbsp root@xiaotianbsp:~#
5.2.4. Clear ring buffer information
root@xiaotianbsp:/# dmesg -c [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Initializing cgroup subsys cpuset [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Initializing cgroup subsys cpuacct ... root@xiaotianbsp:/# dmesg root@xiaotianbsp:/#
dmesg
You can test more usages by yourself.
Note: Please indicate the author and source when reprinting.
RustDesk suspended domestic service Taobao (taobao.com) due to rampant fraud, restarted web version optimization work, Apple released M4 chip, high school students created their own open source programming language as a coming-of-age ceremony - Netizens commented: Relying on the defense, Yunfeng resigned from Alibaba, and plans to produce in the future Visual Studio Code 1.89, the destination for independent game programmers on the Windows platform, is officially announced by Huawei. Yu Chengdong’s job adjustment was nailed to the “FFmpeg Pillar of Shame” 15 years ago, but today he has to thank us - Tencent QQ Video avenges its previous shame? The open source mirror station of Huazhong University of Science and Technology is officially open to external network access