Linux kernel UART

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 4ALinux 4.4RK3399 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.PCCOMRS-232

In embedded systems, serial port generally refers to port. Generally, 3 pins are used and levels are used.UARTTTL

TTL/RS-232/RS-485Refers to the level standard, the difference is as follows:

level standard logic 0 Logic 1 transfer method
TTLlevel 0 ~ 0.4V 2.4 ~ 5V full duplex
RS-232level 3 ~ 15V -15 ~ -3V full duplex
RS-485level -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转TTLPC

RK3399 UARTController 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 UARTThe pin description is shown in the figure below:

2. UART connection

ROCKPi 4AThe board has a 40-pin expansion port, as shown in the picture below:radxa

RockPI 4AThe single board is used as a debugging serial port, and the pin connection method for converting to a serial port is as follows:UART2USBTTL

RockPI4A single board USB to TTL serial port
PIN8(UART2_TXD) RXD
PIN9(GND) GND
PIN10(UART2_RXD) TXD

RockPI 4AThe 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 4ARK3399 DTSUART

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.dtsaliasesserialxttySx

Configuration file: .arch/arm64/boot/dts/rockchip/rk3399.dtsi

RK3399 DTSis 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:UART4ttyS1

    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 dtsThe 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 pinmuxconfiguration, 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 UART0The 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.SPIdtsSPIUART0

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 dtsThe 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/ttyFIQ0console

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 4AFor the system used by the board , set the parameters in the configuration file.Debianextlinux.confconsole

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.4The kernel driver uses the 8250 universal driver, the type is . Main implementation files:UART16550A

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

UARTDrivers 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.Linuxprintk()

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、BuildrootAndroidbootargsloglevel

Note:

no_console_suspendUsed 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

printkThe 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/sshdmesg

dmesgUsage 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:/#

dmesgYou 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
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4702401/blog/5558194