RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux UART開發(fā)指南

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2023-03-06 10:26 ? 次閱讀

Linux UART 開發(fā)指南

1 概述

1.1 編寫目的

介紹 Linux 內(nèi)核中 UART 驅(qū)動(dòng)的接口及使用方法,為 UART 設(shè)備的使用者提供參考。

1.2 適用范圍

表 1-1: 適用產(chǎn)品列表

內(nèi)核版本 驅(qū)動(dòng)文件
Linux-4.9 及以上 sunxi-uart.c

1.3 相關(guān)人員

UART 驅(qū)動(dòng)、及應(yīng)用層的開發(fā)/維護(hù)人員。

2 模塊介紹

2.1 模塊功能介紹

Linux 內(nèi)核中,UART 驅(qū)動(dòng)的結(jié)構(gòu)圖 1 所示, 可以分為三個(gè)層次:

poYBAGQFT2GAGdyWAABDixts2F0833.png

圖 2-1: Linux UART 體系結(jié)構(gòu)圖

Sunxi UART Driver, 負(fù)責(zé) SUNXI 平臺(tái) UART 控制器的初始化、數(shù)據(jù)通信等, 也是我們要實(shí)現(xiàn)的部分。

UART Core, 為 UART 驅(qū)動(dòng)提供了一套 API, 完成設(shè)備和驅(qū)動(dòng)的注冊(cè)等。

TTY core, 實(shí)現(xiàn)了內(nèi)核中所有 TTY 設(shè)備的注冊(cè)和管理。

2.2 相關(guān)術(shù)語介紹

表 2-1: UART 模塊相關(guān)術(shù)語介紹

術(shù)語 解釋說明
Sunxi 指 Allwinner 的一系列 SoC 硬件平臺(tái)
UART Universal Asynchronous Receiver/Transmitter,通用異步收發(fā)傳輸器
Console 控制臺(tái),Linux 內(nèi)核中用于輸出調(diào)試信息的 TTY 設(shè)備
TTY TeleType/TeleTypewriters 的一個(gè)老縮寫,原來指的是電傳打字機(jī),現(xiàn)在泛指和計(jì)算機(jī)串行端口連接的終端設(shè)備。TTY 設(shè)備還包括虛擬控制臺(tái),串口以及偽終端設(shè)備

2.3 源碼結(jié)構(gòu)介紹

linux4.9

|-- drivers

| |-- tty

| | |-- serial

| | |-- serial_core.c

| | |-- sunxi-uart.c

| | |-- sunxi-uart.h

3 模塊配置介紹

3.1 kernel menuconfig 配置

在 longan 頂層目錄,執(zhí)行./build.sh menuconfig(需要先執(zhí)行./build.sh config) 進(jìn)入配置主界面,并按以下步驟操作:首先,選擇 Device Drivers 選項(xiàng)進(jìn)入下一級(jí)配置,如下圖所示:

pYYBAGQFT2KAbj_WAAG4sCni2Y0946.png

圖 3-1: 內(nèi)核 menuconfig 根菜單

選擇 Character devices, 進(jìn)入下級(jí)配置,如下圖所示:

poYBAGQFT2KAUFiTAALPGjuvxl4802.png

圖 3-2: 內(nèi)核 menuconfig device drivers 菜單

選擇 Serial drivers, 進(jìn)入下級(jí)配置,如下圖所示:

pYYBAGQFT2OAONt8AANQqhSQGmo150.png

圖 3-3: 內(nèi)核 menuconfig Character drivers 菜單

選擇 SUNXI UART Controller 和 Console on SUNXI UART port 選項(xiàng),如下圖:

pYYBAGQFT2SAOCacAAJaC_cQppc052.png

圖 3-4: 內(nèi)核 menuconfig sunxi uart 配置菜單

如果需要 UART 支持 DMA 傳輸,則可以打開 SUNXI UART USE DMA 選項(xiàng)。

3.2 device tree 源碼結(jié)構(gòu)和路徑

? 設(shè)備樹文件的配置是該 SoC 所有方案的通用配置,對(duì)于 ARM64 CPU 而言,設(shè)備樹的路徑為內(nèi)核目錄下:arch/arm64/boot/dts/sunxi/sun*.dtsi。

? 設(shè)備樹文件的配置是該 SoC 所有方案的通用配置,對(duì)于 ARM32 CPU 而言,設(shè)備樹的路徑為內(nèi)核目錄下:arch/arm/boot/dts/sun*.dtsi。

? 板級(jí)設(shè)備樹 (board.dts) 路徑:/device/config/chips/{IC}/configs/{BOARD}/board.dts。device tree 的源碼結(jié)構(gòu)關(guān)系如下:

device tree 的源碼結(jié)構(gòu)關(guān)系如下:

linux-4.9

board.dts

|--------sun*.dtsi

|------sun*-pinctrl.dtsi

|------sun*-clk.dtsi

linux-5.4

board.dts

|-------sun*.dtsi

3.2.1 device tree 對(duì) uart 控制器的通用配置

linux-4.9 的通用配置如下:

/ {

model = "sun*";

compatible = "arm,sun*";

interrupt-parent = <&wakeupgen>;

#address-cells = <2>;

#size-cells = <2>;

aliases {

serial0 = &uart0;

serial1 = &uart1;

serial2 = &uart2;

serial3 = &uart3;

serial4 = &uart4;

serial5 = &uart5;

...

};

?

uart0: uart@05000000 {

compatible = "allwinner,sun50i-uart"; /* 用于驅(qū)動(dòng)和設(shè)備綁定 */

device_type = "uart0"; /* 設(shè)備類型*/

reg = <0x0 0x05000000 0x0 0x400>; /* 設(shè)備使用的寄存器基地址以及范圍*/

interrupts = ; /* 設(shè)備使用的硬件中斷號(hào)*/

clocks = <&clk_uart0>; /* 設(shè)備使用的時(shí)鐘*/

pinctrl-names = "default", "sleep";

pinctrl-0 = <&uart0_pins_a>; /* 設(shè)備正常狀態(tài)下使用的pin腳*/

pinctrl-1 = <&uart0_pins_b>; /* 設(shè)備休眠狀態(tài)下使用的pin腳*/

uart0_port = <0>; /* uart控制器對(duì)應(yīng)的ttyS唯一端口號(hào),不能與其他uart控制器重復(fù)*/

uart0_type = <2>; /* uart控制器線數(shù),取值2/4/8*/

use_dma = <0>; /* 是否采用DMA 方式傳輸,0:不啟用,1:只啟用TX,2:只啟用RX,3:?jiǎn)?用TX 與RX*/

status = "okay"; /* 是否使能該節(jié)點(diǎn)*/

};

linux-5.4 的通用配置如下:

uart0: uart@5000000 {

compatible = "allwinner,sun50i-uart";

device_type = "uart0";

reg = <0x0 0x05000000 0x0 0x400>;

interrupts = ;

sunxi,uart-fifosize = <64>;

clocks = <&ccu CLK_BUS_UART0>; /* 設(shè)備使用的時(shí)鐘 */

clock-names = "uart0";

resets = <&ccu RST_BUS_UART0>; /* 設(shè)備reset時(shí)鐘 */

pinctrl-names = "default", "sleep";

pinctrl-0 = <&uart0_pins_a>;

pinctrl-1 = <&uart0_pins_b>;

uart0_port = <0>;

uart0_type = <2>;

dmas = <&dma 14>; /* 14表示DRQ */

dma-names = "tx";

use_dma = <0>; /* 是否采用DMA 方式傳輸,0:不啟用,1:只啟用TX,2:只啟用RX,3:?jiǎn)⒂肨X 與RX */

};

在 Device Tree 中對(duì)每一個(gè) UART 控制器進(jìn)行配置, 一個(gè) UART 控制器對(duì)應(yīng)一個(gè) UART 節(jié)點(diǎn), 節(jié)點(diǎn)屬性的含義見注釋。為了在 UART 驅(qū)動(dòng)代碼中區(qū)分每一個(gè) UART 控制器,需要在 Device Tree 中的 aliases 節(jié)點(diǎn)中未每一個(gè)。UART 節(jié)點(diǎn)指定別名,如上 aliases 節(jié)點(diǎn)所示。別名形式為字符串 “serial” 加連續(xù)編號(hào)的數(shù)字,在 UART 驅(qū)動(dòng)程序中可以通過 of_alias_get_id() 函數(shù)獲取對(duì)應(yīng)的 UART 控制器的數(shù)字編號(hào),從而區(qū)分每一個(gè) UART 控制器。

3.2.2 board.dts 板級(jí)配置

board.dts 用于保存每個(gè)板級(jí)平臺(tái)的設(shè)備信息 (如 demo 板、demo2.0 板等等),board.dts 路徑如下:/device/config/chips/{IC}/configs/{BOARD}/board.dts。

在 board.dts 中的配置信息如果在 *.dtsi(如 sun50iw9p1.dtsi 等) 存在,則會(huì)存在以下覆蓋規(guī)則:

相同屬性和結(jié)點(diǎn),board.dts 的配置信息會(huì)覆蓋 *.dtsi 中的配置信息。

新增加的屬性和結(jié)點(diǎn),會(huì)添加到編譯生成的 dtb 文件中。

uart 在 board.dts 的簡(jiǎn)單配置如下:

soc@03000000 {

...

&uart0 {

uart-supply = ; /* IO使用的電 */

status = "okay";

};

?

&uart1 {

status = "okay";

};

...

}

3.2.3 uart dma 模式配置

在內(nèi)核配置菜單打開 CONFIG_SERIAL_SUNXI_DMA 配置,如下圖所示:

poYBAGQFT2WAUZLxAAJoBzvJzC8265.png

圖 3-5: 內(nèi)核 menuconfig sunxi uart 配置菜單

在對(duì)應(yīng) dts 配置使用 dma,如下所示:

Linux-4.9 配置如下:

uart1: uart@05000400 {

...

use_dma = <3>; /* 是否采用DMA 方式傳輸,0:不啟用,1:只啟用TX,2:只啟用RX,3:?jiǎn)⒂肨X 與RX */

status = "okay";

};

linux-5.4 配置如下:

uart0: uart@5000000 {

...

dmas = <&dma 14>; /* 14表示DRQ, 查看dma spec */

dma-names = "tx";

use_dma = <0>; /* 是否采用DMA 方式傳輸,0:不啟用,1:只啟用TX,2:只啟用RX,3:?jiǎn)⒂肨X 與RX

*/

};

3.2.4 設(shè)置其他 uart 為打印 conole

從 dts 確保設(shè)置為 console 的 uart 已經(jīng)使能,如 uart1。

uart1: uart@05000400 {

compatible = "allwinner,sun50i-uart";

device_type = "uart1";

reg = <0x0 0x05000400 0x0 0x400>;

interrupts = ;

clocks = <&clk_uart1>;

pinctrl-names = "default", "sleep";

pinctrl-0 = <&uart1_pins_a>;

pinctrl-1 = <&uart1_pins_b>;

uart1_port = <1>;

uart1_type = <4>;

status = "okay"; /* 確保該uart已經(jīng)使能 */

};

修改方案使用的 env*.cfg 文件,如下所示:

console=ttyS1,115200 說明: ttyS0 <===> uart0 ttyS1 <===> uart1 ...

3.2.5 設(shè)置 uart 波特率

在不同的 Sunxi 硬件平臺(tái)中,UART 控制器的時(shí)鐘源選擇、配置略有不同,總體上的時(shí)鐘關(guān)系如下:

pYYBAGQFT2aAblvhAAAwhZs8_VE737.png

圖 3-6: 時(shí)鐘說明

UART 控制器會(huì)對(duì)輸入的時(shí)鐘源進(jìn)行分頻,最終輸出一個(gè)頻率滿足(或近似)UART 波特率的時(shí)鐘信號(hào)。UART 常用的標(biāo)準(zhǔn)波特率有:

#define B4800 0000014 #define B9600 0000015 #define B19200 0000016 #define B38400 0000017 #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 #define B460800 0010004 #define B500000 0010005 #define B576000 0010006 #define B921600 0010007 #define B1000000 0010010 #define B1152000 0010011 #define B1500000 0010012 #define B2000000 0010013 #define B2500000 0010014 #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017

UART 時(shí)鐘的分頻比是 16 的整數(shù)倍,分頻難免會(huì)有誤差,所以輸出 UART Device 通信的波特率是否足夠精準(zhǔn),很大程度取決于輸入的時(shí)鐘源頻率??紤]到功耗,UART 驅(qū)動(dòng)中一般默認(rèn)使用 24M 時(shí)鐘源,但是根據(jù)應(yīng)用場(chǎng)景我們有時(shí)候需要切換別的時(shí)鐘源,基于兩個(gè)原因:

24MHz/16=1.5MHz,這個(gè)最大頻率滿足不了 1.5M 以上的波特率應(yīng)用;

24M 分頻后得到波特率誤差可能太大,也滿足不了某些 UART 外設(shè)的冗余要求(一般要求 2% 或 5% 以內(nèi),由外設(shè)決定)。UART 時(shí)鐘源來自 APB2,APB2 的時(shí)鐘源有兩個(gè),分別是 24MHz(HOSC)和 PLL_PERIPH(即驅(qū)動(dòng)中的 PLL_PERIPH_CLK),系統(tǒng)默認(rèn)配置 APB2 的時(shí)鐘源是 24M,如果要提高UART 的時(shí)鐘就要將 APB2 的時(shí)鐘源設(shè)置為 PLL_PERIPH。同時(shí)要注意到 APB2 也是 TWI 的時(shí)鐘源,所以需要兼顧 TWI 時(shí)鐘。

各個(gè) uart 波特率對(duì)應(yīng)頻點(diǎn)關(guān)系如下:

poYBAGQFT2aATOEjAABLq2w4iXc866.png

圖 3-7: 波特率關(guān)系

例如需要配置 uart2 的波特率為 460800,在上述關(guān)系表中可以看出,對(duì)應(yīng)的時(shí)鐘為 30M、37.5M、42.857M、46.153M 和 50M 等,所以需要在設(shè)備樹里修改 uart2 時(shí)鐘:

linux-4.9 修改波特率如下:

device_type = "uart2"; reg = <0x0 0x05000800 0x0 0x400>; interrupts = ; - clocks = <&clk_uart2>; + clocks = <&clk_uart2>, <&clk_apb2>, <&clk_psi>; + clock-frequency = <50000000>; pinctrl-names = "default", "sleep";

有的情況下,APB2 不一定能準(zhǔn)確分出 30M 或者 37.5M 等時(shí)鐘,所以這里我們選擇配置為 50M 時(shí)鐘。

如果我們修改了 APB2 時(shí)鐘,可能會(huì)對(duì) uart0 有影響,啟動(dòng)串口會(huì)出現(xiàn)亂碼,那么我們最好也將 uart0 的時(shí)鐘配置為 50M 時(shí)鐘。

device_type = "uart0"; reg = <0x0 0x05000000 0x0 0x400>; interrupts = ; - clocks = <&clk_uart0>; + clocks = <&clk_uart0>, <&clk_apb2>, <&clk_psi>; + clock-frequency = <50000000>; pinctrl-names = "default", "sleep";

linux-5.4 修改波特率如下:

device_type = "uart2"; reg = <0x0 0x05000800 0x0 0x400>; interrupts = ; - clocks = <&clk_uart2>; + clocks = <&ccu CLK_BUS_UART0>, + <&ccu CLK_APB2>, + <&ccu CLK_PSI_AHB1_AHB2>; + clock-frequency = <50000000>; pinctrl-names = "default", "sleep";

說明

修改 APB2 總線時(shí)鐘,會(huì)影響到使用到 APB2 總線時(shí)鐘的相應(yīng)模塊。

3.2.6 支持 cpus 域的 uart

在不同的 Sunxi 硬件平臺(tái)中,UART 控制器根據(jù)電源域劃分了 CPUX 域和 CPUS 域,系統(tǒng)默認(rèn)對(duì) CPUX 域的 uart 控制器都會(huì)默認(rèn)配置上,但對(duì) CPUS 域的 uart 控制器可能沒有支持上,當(dāng)希望通過 CPUX 使用 CPUS 域的 uart 時(shí),請(qǐng)參考以下步驟進(jìn)行支持:

通過 datasheet 或者 spec,獲取 CPUS 域 uart 控制器的 pin 腳、clk、控制器地址等信息。

確保 cpus 運(yùn)行的系統(tǒng)沒有使用到 CPUS 域的 uart 控制器,只有 CPUX 域在使用。

在 r_pio 域配置 pin 的 dtsi 文件 (*.-pinctrl.dtsi)。

/ { soc@03000000{ r_pio: pinctrl@07022000 { ... /* 配置CPUS域uart pin信息 */ s_uart0_pins_a: s_uart0@0 { allwinner,pins = "PL2", "PL3"; allwinner,function = "s_uart0"; allwinner,muxsel = <2>; allwinner,drive = <1>; allwinner,pull = <1>; }; ... }; ... };

在 clk dtsi 配置時(shí)鐘信息 (*-clk.dtsi)。

clk_suart0: suart0 { #clock-cells = <0>; compatible = "allwinner,periph-cpus-clock"; clock-output-names = "suart0"; };

在 dtsi 配置 uart 控制器信息 (*.dtsi)。

aliases { serial0 = &uart0; ... serial5 = &uart5; //添加uart5的別名,必須要添加 }; uart0:uart@05000000 { }; .... /* 添加uart控制器信息 ,必須要添加,具體屬性含義,見上文 */ uart5: uart@07080000 { compatible = "allwinner,sun8i-uart"; device_type = "uart5"; reg = <0x0 0x07080000 0x0 0x400>; interrupts = ; clocks = <&clk_suart0>; pinctrl-names = "default", "sleep"; pinctrl-1 = <&s_uart0_pins_a>; uart5_port = <5>; uart5_type = <2>; status = "okay"; };

檢查或添加 pin 描述符。

有可能 pinctrl 驅(qū)動(dòng)里,沒有把 CPUS 域 uart 控制器的 pin 描述出來,因此要的 pinctrl 驅(qū)動(dòng)里檢查或添加 pin 的描述信息,查看 pinctrl-*-r.c 文件。

static const struct sunxi_desc_pin *_r_pins[] = { SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0), ... SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2), ... SUNXI_FUNCTION(0x2, "s_uart0"), //沒有則要添加 ... SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3), ... SUNXI_FUNCTION(0x2, "s_uart0"), //沒有則要添加 ... };

檢查 clk 的描述信息。

有可能 clk 驅(qū)動(dòng)根據(jù)情況,也沒有把 CPUS 域的 uart 控制器的時(shí)鐘信息描述出來,因此要 clk 驅(qū)動(dòng)里檢查或添加 clk 的描述信息,查看 clk-.cclk-.h 文件。

/* clk-*.h */ #define CPUS_UART_GATE 0x018C /* clk-*.c */ static const char *suart_parents[] = {"cpurapbs2"}; SUNXI_CLK_PERIPH(suart0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CPUS_UART_GATE, CPUS_UART_GATE, 0, 0, 16, 0, 0, &clk_lock, NULL, 0); struct periph_init_data sunxi_periphs_cpus_init[] = { ... {"suart0", 0, suart_parents, ARRAY_SIZE(suart_parents), &sunxi_clk_periph_suart0 }, };

檢查 uart 驅(qū)動(dòng)支持的 uart 數(shù)量是否足夠,查看 sunxi-uart.h 文件。

通過 SUNXI_UART_NUM 宏確認(rèn)支持 uart 的數(shù)量。

修改完畢后,啟動(dòng)小機(jī),查看 ttySn 設(shè)備是否生成,通過該設(shè)備測(cè)試 uart 是否正常使用即可。

4 接口描述

UART 驅(qū)動(dòng)會(huì)注冊(cè)生成串口設(shè)備/dev/ttySx,應(yīng)用層的使用只需遵循 Linux 系統(tǒng)中的標(biāo)準(zhǔn)串口編程方法即可。

4.1 打開/關(guān)閉串口

使用標(biāo)準(zhǔn)的文件打開函數(shù):

int open(const char *pathname, int flags); int close(int fd);

需要引用頭文件:

#include #include #include #include

4.2 讀/寫串口

同樣使用標(biāo)準(zhǔn)的文件讀寫函數(shù):

ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count);

需要引用頭文件:

#include

4.3 設(shè)置串口屬性

串口屬性包括波特率、數(shù)據(jù)位、停止位、校驗(yàn)位、流控等,這部分是串口設(shè)備特有的接口。串口屬性的數(shù)據(jù)結(jié)構(gòu) termios 定義如下:(terminos.h)。

#define NCCS 19 struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_line; /* line discipline */ cc_t c_cc[NCCS]; /* control characters */ };

其中,c_iflag 的標(biāo)志常量定義如下:

標(biāo)志 說明
IGNBRK 忽略輸入中的 BREAK 狀態(tài)。
BRKINT 如果設(shè)置了 IGNBRK,將忽略 BREAK。如果沒有設(shè)置,但是設(shè)置了 BRKINT,那么 BREAK 將使得輸入和輸出隊(duì)列被刷新,如果終端是一個(gè)前臺(tái)進(jìn)程組的控制終端,這個(gè)進(jìn)程組中所有進(jìn)程將收到 SIGINT 信號(hào)。如果既未設(shè)置 IGNBRK 也未設(shè)置 BRKINT,BREAK 將視為與 NUL 字符同義,除非設(shè)置了 PARMRK,這種情況下它被視為序列 377 ? ?。
IGNPAR 忽略楨錯(cuò)誤和奇偶校驗(yàn)錯(cuò)。
PARMRK 如果沒有設(shè)置 IGNPAR,在有奇偶校驗(yàn)錯(cuò)或楨錯(cuò)誤的字符前插入 377 ?。如果既沒有設(shè)置 IGNPAR 也沒有設(shè)置 PARMRK,將有奇偶校驗(yàn)錯(cuò)或楨錯(cuò)誤的字符視為 ?。
INPCK 啟用輸入奇偶檢測(cè)。
ISTRIP 去掉第八位。
INLCR 將輸入中的 NL 翻譯為 CR。
IGNCR 忽略輸入中的回車。
ICRNL 將輸入中的回車翻譯為新行 (除非設(shè)置了 IGNCR)。
IUCLC (不屬于 POSIX) 將輸入中的大寫字母映射為小寫字母。
IXON 啟用輸出的 XON/XOFF 流控制。
IXANY (不屬于 POSIX.1;XSI) 允許任何字符來重新開始輸出。
IXOFF 啟用輸入的 XON/XOFF 流控制。
IMAXBEL (不屬于 POSIX) 當(dāng)輸入隊(duì)列滿時(shí)響零。Linux 沒有實(shí)現(xiàn)這一位,總是將它視為已設(shè)置。

c_oflag 的標(biāo)志常量定義如下:

標(biāo)志 說明
OLCUC (不屬于 POSIX) 將輸出中的小寫字母映射為大寫字母。
ONLCR (XSI) 將輸出中的新行符映射為回車-換行。
OCRNL 將輸出中的回車映射為新行符。
ONOCR 不在第 0 列輸出回車。
ONLRET 不輸出回車。
OFILL 發(fā)送填充字符作為延時(shí),而不是使用定時(shí)來延時(shí)。
OFDEL (不屬于 POSIX) 填充字符是 ASCII DEL (0177)。如果不設(shè)置,填充字符則是 ASCII NUL。
NLDLY 新行延時(shí)掩碼。取值為 NL0 和 NL1。
CRDLY 回車延時(shí)掩碼。取值為 CR0, CR1, CR2, 或 CR3。
TABDLY 水平跳格延時(shí)掩碼。取值為 TAB0, TAB1, TAB2, TAB3 (或 XTABS)。取值為 TAB3,即 XTABS,將擴(kuò)展跳格為空格 (每個(gè)跳格符填充 8 個(gè)空格)。
BSDLY 回退延時(shí)掩碼。取值為 BS0 或 BS1。(從來沒有被實(shí)現(xiàn)過)。
VTDLY 豎直跳格延時(shí)掩碼。取值為 VT0 或 VT1。
FFDLY 進(jìn)表延時(shí)掩碼。取值為 FF0 或 FF1。

c_cflag 的標(biāo)志常量定義如下:

標(biāo)志 說明
CBAUD (不屬于 POSIX) 波特率掩碼 (4+1 位)。
CBAUDEX (不屬于 POSIX) 擴(kuò)展的波特率掩碼 (1 位),包含在 CBAUD 中。(POSIX 規(guī)定波特率存儲(chǔ)在 termios 結(jié)構(gòu)中,并未精確指定它的位置,而是提供了函數(shù) cfgetispeed() 和 cfsetispeed() 來存取它。一些系統(tǒng)使用 c_cflag 中CBAUD 選擇的位,其他系統(tǒng)使用單獨(dú)的變量,例如 sg_ispeed 和sg_ospeed 。)
CSIZE 字符長(zhǎng)度掩碼。取值為 CS5, CS6, CS7, 或 CS8。
CSTOPB 設(shè)置兩個(gè)停止位,而不是一個(gè)。
CREAD 打開接受者。
PARENB 允許輸出產(chǎn)生奇偶信息以及輸入的奇偶校驗(yàn)。
PARODD 輸入和輸出是奇校驗(yàn)。
HUPCL 在最后一個(gè)進(jìn)程關(guān)閉設(shè)備后,降低 modem 控制線 (掛斷)。
CLOCAL 忽略 modem 控制線。
LOBLK (不屬于 POSIX) 從非當(dāng)前 shell 層阻塞輸出 (用于 shl )。
CIBAUD (不屬于 POSIX) 輸入速度的掩碼。CIBAUD 各位的值與 CBAUD 各位相同,左移了 IBSHIFT 位。
CRTSCTS (不屬于 POSIX) 啟用 RTS/CTS (硬件) 流控制

c_lflag 的標(biāo)志常量定義如下:

標(biāo)志 說明
ISIG 當(dāng)接受到字符 INTR, QUIT, SUSP, 或 DSUSP 時(shí),產(chǎn)生相應(yīng)的信號(hào)。
ICANON 啟用標(biāo)準(zhǔn)模式 (canonical mode)。允許使用特殊字符 EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, 和 WERASE,以及按行的緩沖。
XCASE (不屬于 POSIX; Linux 下不被支持) 如果同時(shí)設(shè)置了 ICANON,終端只有大寫。輸入被轉(zhuǎn)換為小寫,除了以 前綴的字符。輸出時(shí),大寫字符被前綴,小寫字符被轉(zhuǎn)換成大寫。
ECHO 回顯輸入字符。
ECHOE 如果同時(shí)設(shè)置了 ICANON,字符 ERASE 擦除前一個(gè)輸入字符,WERASE 擦除前一個(gè)詞。
ECHOK 如果同時(shí)設(shè)置了 ICANON,字符 KILL 刪除當(dāng)前行。
ECHONL 如果同時(shí)設(shè)置了 ICANON,回顯字符 NL,即使沒有設(shè)置 ECHO。
ECHOCTL (不屬于 POSIX) 如果同時(shí)設(shè)置了 ECHO,除了 TAB, NL, START, 和 STOP 之外的 ASCII 控制信號(hào)被回顯為 ?X, 這里 X 是比控制信號(hào)大 0x40 的 ASCII 碼。例如,字符 0x08 (BS) 被回顯為 ?H。
ECHOPRT (不屬于 POSIX) 如果同時(shí)設(shè)置了 ICANON 和 IECHO,字符在刪除的同時(shí)被打印。
ECHOKE (不屬于 POSIX) 如果同時(shí)設(shè)置了 ICANON,回顯 KILL 時(shí)將刪除一行中的每個(gè)字符,如同指定了 ECHOE 和 ECHOPRT 一樣。
DEFECHO (不屬于 POSIX) 只在一個(gè)進(jìn)程讀的時(shí)候回顯。
FLUSHO (不屬于 POSIX; Linux 下不被支持) 輸出被刷新。這個(gè)標(biāo)志可以通過鍵入字符 DISCARD 來開關(guān)。
NOFLSH 禁止在產(chǎn)生 SIGINT, SIGQUIT 和 SIGSUSP 信號(hào)時(shí)刷新輸入和輸出隊(duì)列。
PENDIN (不屬于 POSIX; Linux 下不被支持) 在讀入下一個(gè)字符時(shí),輸入隊(duì)列中所有字符被重新輸出。(bash 用它來處理 typeahead)
TOSTOP 向試圖寫控制終端的后臺(tái)進(jìn)程組發(fā)送 SIGTTOU 信號(hào)。
IEXTEN 啟用實(shí)現(xiàn)自定義的輸入處理。這個(gè)標(biāo)志必須與 ICANON 同時(shí)使用,才能解釋特殊字符 EOL2,LNEXT,REPRINT 和 WERASE,IUCLC 標(biāo)志才有效。

c_cc 數(shù)組定義了特殊的控制字符。符號(hào)下標(biāo) (初始值) 和意義為:

標(biāo)志 說明
VINTR (003, ETX, Ctrl-C, or also 0177, DEL, rubout) 中斷字符。發(fā)出 SIGINT 信號(hào)。當(dāng)設(shè)置 ISIG 時(shí)可被識(shí)別,不再作為輸入傳遞。
VQUIT (034, FS, Ctrl-) 退出字符。發(fā)出 SIGQUIT 信號(hào)。當(dāng)設(shè)置 ISIG 時(shí)可被識(shí)別,不再作為輸入傳遞。
VERASE (0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) 刪除字符。刪除上一個(gè)還沒有刪掉的字符,但不刪除上一個(gè) EOF 或行首。當(dāng)設(shè)置 ICANON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VKILL (025, NAK, Ctrl-U, or Ctrl-X, or also @) 終止字符。刪除自上一個(gè) EOF 或行首以來的輸入。當(dāng)設(shè)置 ICANON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VEOF (004, EOT, Ctrl-D) 文件尾字符。更精確地說,這個(gè)字符使得 tty 緩沖中的內(nèi)容被送到等待輸入的用戶程序中,而不必等到 EOL。如果它是一行的第一個(gè)字符,那么用戶程序的 read() 將返回 0,指示讀到了 EOF。當(dāng)設(shè)置 ICANON時(shí)可被識(shí)別,不再作為輸入傳遞。
VMIN 非 canonical 模式讀的最小字符數(shù)。
VEOL (0, NUL) 附加的行尾字符。當(dāng)設(shè)置 ICANON 時(shí)可被識(shí)別。
VTIME 非 canonical 模式讀時(shí)的延時(shí),以十分之一秒為單位。
VEOL2 (not in POSIX; 0, NUL) 另一個(gè)行尾字符。當(dāng)設(shè)置 ICANON 時(shí)可被識(shí)別。
VSTART (021, DC1, Ctrl-Q) 開始字符。重新開始被 Stop 字符中止的輸出。當(dāng)設(shè)置 IXON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VSTOP (023, DC3, Ctrl-S) 停止字符。停止輸出,直到鍵入 Start 字符。當(dāng)設(shè)置 IXON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VSUSP (032, SUB, Ctrl-Z) 掛起字符。發(fā)送 SIGTSTP 信號(hào)。當(dāng)設(shè)置 ISIG 時(shí)可被識(shí)別,不再作為輸入傳遞。
VLNEXT (not in POSIX; 026, SYN, Ctrl-V) 字面上的下一個(gè)。引用下一個(gè)輸入字符,取消它的任何特殊含義。當(dāng)設(shè)置 IEXTEN 時(shí)可被識(shí)別,不再作為輸入傳遞。
VSTART (021, DC1, Ctrl-Q) 開始字符。重新開始被 Stop 字符中止的輸出。當(dāng)設(shè)置 IXON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VSTOP (023, DC3, Ctrl-S) 停止字符。停止輸出,直到鍵入 Start 字符。當(dāng)設(shè)置 IXON 時(shí)可被識(shí)別,不再作為輸入傳遞。
VSUSP (032, SUB, Ctrl-Z) 掛起字符。發(fā)送 SIGTSTP 信號(hào)。當(dāng)設(shè)置 ISIG 時(shí)可被識(shí)別,不再作為輸入傳遞。
VLNEXT (not in POSIX; 026, SYN, Ctrl-V) 字面上的下一個(gè)。引用下一個(gè)輸入字符,取消它的任何特殊含義。當(dāng)設(shè)置 IEXTEN 時(shí)可被識(shí)別,不再作為輸入傳遞。
VWERASE (not in POSIX; 027, ETB, Ctrl-W) 刪除詞。當(dāng)設(shè)置 ICANON 和 IEXTEN 時(shí)可被識(shí)別,不再作為輸入傳遞。
VREPRINT (not in POSIX; 022, DC2, Ctrl-R) 重新輸出未讀的字符。當(dāng)設(shè)置 ICANON和 IEXTEN 時(shí)可被識(shí)別,不再作為輸入傳遞。

4.3.1 tcgetattr

? 作用:獲取串口設(shè)備的屬性。

? 參數(shù)

? fd,串口設(shè)備的文件描述符。

? termios_p,用于保存串口屬性。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼。

4.3.2 tcsetattr

? 作用:設(shè)置串口設(shè)備的屬性。

? 參數(shù):

? fd,串口設(shè)備的文件描述符。

? optional_actions,本次設(shè)置什么時(shí)候生效。

? termios_p,指向要設(shè)置的屬性結(jié)構(gòu)。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼

說明

其中,optional_actions的取值有:

TCSANOW:會(huì)立即生效。

TCSADRAIN:當(dāng)前的輸出數(shù)據(jù)完成傳輸后生效,適用于修改了輸出相關(guān)的參數(shù)。

TCSAFLUSH:當(dāng)前的輸出數(shù)據(jù)完成傳輸,如果輸入有數(shù)據(jù)可讀但沒有讀就會(huì)被丟棄。

4.3.3 cfgetispeed

? 作用:返回串口屬性中的輸入波特率。

? 參數(shù):

? termios_p,指向保存有串口屬性的結(jié)構(gòu)。

? 返回:

? 成功,返回波特率,取值是一組宏,定義在 terminos.h。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼。

說明

波特率定義如下所示:

#define B0 0000000

#define B50 0000001

#define B75 0000002

#define B110 0000003

#define B134 0000004

#define B150 0000005

#define B200 0000006

#define B300 0000007

#define B600 0000010

#define B1200 0000011

#define B1800 0000012

#define B2400 0000013

#define B4800 0000014

#define B9600 0000015

#define B19200 0000016

#define B38400 0000017

#define B57600 0010001

#define B115200 0010002

#define B230400 0010003

#define B460800 0010004

#define B500000 0010005

#define B576000 0010006

#define B921600 0010007

#define B1000000 0010010

#define B1152000 0010011

#define B1500000 0010012

#define B2000000 0010013

#define B2500000 0010014

#define B3000000 0010015

#define B3500000 0010016

#define B4000000 0010017

4.3.4 cfgetospeed

? 作用:返回串口屬性中的輸出波特率。

? 參數(shù):

? termios_p,指向保存有串口屬性的結(jié)構(gòu)。

? 返回:

? 成功,返回波特率,取值是一組宏,定義在 terminos.h,見 4.3.3

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼。

4.3.5 cfsetispeed

? 作用:設(shè)置輸入波特率到屬性結(jié)構(gòu)中。

? 參數(shù):

? termios_p,指向保存有串口屬性的結(jié)構(gòu)。

? speed,波特率,取值同 4.3.3。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼

4.3.6 cfsetospeed

? 作用:設(shè)置輸出波特率到屬性結(jié)構(gòu)中。

? 參數(shù):

? termios_p,指向保存有串口屬性的結(jié)構(gòu)。

? speed,波特率,取值同 4.3.3。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼

4.3.7 cfsetspeed

? 作用:同時(shí)設(shè)置輸入和輸出波特率到屬性結(jié)構(gòu)中。

? 參數(shù):

? termios_p,指向保存有串口屬性的結(jié)構(gòu)。

? speed,波特率,取值同 4.3.3。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼

4.3.8 tcflush

? 作用:清空輸出緩沖區(qū)、或輸入緩沖區(qū)的數(shù)據(jù),具體取決于參數(shù) queue_selector。

? 參數(shù):

? fd,串口設(shè)備的文件描述符。

? queue_selector,清空數(shù)據(jù)的操作。

? 返回:

? 成功,返回 0。

? 失敗,返回-1,errnor 給出具體錯(cuò)誤碼。

說明

參數(shù) queue_selector 的取值有三個(gè):

TCIFLUSH:清空輸入緩沖區(qū)的數(shù)據(jù)。

TCOFLUSH:清空輸出緩沖區(qū)的數(shù)據(jù)。

TCIOFLUSH:同時(shí)清空輸入/輸出緩沖區(qū)的數(shù)據(jù)。

5 模塊使用范例

此 demo 程序是打開一個(gè)串口設(shè)備,然后偵聽這個(gè)設(shè)備,如果有數(shù)據(jù)可讀就讀出來并打印。設(shè)備名稱、偵聽的循環(huán)次數(shù)都可以由參數(shù)指定。

#include /*標(biāo)準(zhǔn)輸入輸出定義*/ #include /*標(biāo)準(zhǔn)函數(shù)庫定義*/ #include /*Unix 標(biāo)準(zhǔn)函數(shù)定義*/ #include #include #include /*文件控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯(cuò)誤號(hào)定義*/ #include enum parameter_type { PT_PROGRAM_NAME = 0, PT_DEV_NAME, PT_CYCLE, PT_NUM }; #define DBG(string, args...) do { printf("%s, %s()%u---", __FILE__, __FUNCTION__, __LINE__); printf(string, _00args); printf("n"); } while (0) void usage(void) { printf("You should input as: n"); printf("t select_test [/dev/name] [Cycle Cnt]n"); } int OpenDev(char *name) { int fd = open(name, O_RDWR ); //| O_NOCTTY | O_NDELAY if (-1 == fd) DBG("Can't Open(%s)!", name); return fd; } /** * @brief 設(shè)置串口通信速率 * @param fd 類型 int 打開串口的文件句柄 * @param speed 類型 int 串口速度 * @return void */ void set_speed(int fd, int speed) { int i; int status; struct termios Opt = {0}; int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; tcgetattr(fd, &Opt); for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { ? ? ? ?if (speed == name_arr[i]) ? ? ? ?break; ? ?} ? ?tcflush(fd, TCIOFLUSH); ? ?cfsetispeed(&Opt, speed_arr[i]); ? ?cfsetospeed(&Opt, speed_arr[i]); ? ?Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ ? ?Opt.c_oflag &= ~OPOST; /*Output*/ ? ?status = tcsetattr(fd, TCSANOW, &Opt); ? ?if (status != 0) { ? ? ? ?DBG("tcsetattr fd"); ? ? ? ?return; ? ?} ? ?tcflush(fd, TCIOFLUSH); } /** *@brief 設(shè)置串口數(shù)據(jù)位,停止位和效驗(yàn)位 *@param fd 類型 int 打開的串口文件句柄 *@param databits 類型 int 數(shù)據(jù)位 取值 為 7 或者8 *@param stopbits 類型 int 停止位 取值為 1 或者2 *@param parity 類型 int 效驗(yàn)類型 取值為N,E,O,,S */ int set_Parity(int fd,int databits,int stopbits,int parity) { ? ?struct termios options; ? ?if ( tcgetattr(fd, &options) != 0) { ? ? ? ?perror("SetupSerial 1"); ? ? ? ?return -1; ? ?} ? ?options.c_cflag &= ~CSIZE; ? ?switch (databits) /*設(shè)置數(shù)據(jù)位數(shù)*/ ? ?{ ? ? ? ?case 7: ? ? ? ? ? ?options.c_cflag |= CS7; ? ? ? ? ? ?break; ? ? ? ?case 8: ? ? ? ? ? ?options.c_cflag |= CS8; ? ? ? ? ? ?break; ? ? ? ?default: ? ? ? ? ? ?fprintf(stderr,"Unsupported data sizen"); ? ? ? ? ? ?return -1; ? ?} ? ? ? ?switch (parity) ? ?{ ? ? ? ?case 'n': ? ? ? ?case 'N': ? ? ? ? ? ?options.c_cflag &= ~PARENB; /* Clear parity enable */ ? ? ? ? ? ?options.c_iflag &= ~INPCK; /* Enable parity checking */ ? ? ? ? ? ?break; ? ? ? ?case 'o': ? ? ? ?case 'O': ? ? ? ? ? ?options.c_cflag |= (PARODD | PARENB); /* 設(shè)置為奇效驗(yàn)*/ ? ? ? ? ? ?options.c_iflag |= INPCK; /* Disnable parity checking */ ? ? ? ? ? ?break; ? ? ? ?case 'e': ? ? ? ?case 'E': ? ? ? ? ? ?options.c_cflag |= PARENB; /* Enable parity */ ? ? ? ? ? ?options.c_cflag &= ~PARODD; /* 轉(zhuǎn)換為偶效驗(yàn)*/ ? ? ? ? ? ?options.c_iflag |= INPCK; /* Disnable parity checking */ ? ? ? ? ? ?break; ? ? ? ?case 'S': ? ? ? ?case 's': /*as no parity*/ ? ? ? ? ? ?options.c_cflag &= ~PARENB; ? ? ? ? ? ?options.c_cflag &= ~CSTOPB;break; ? ? ? ?default: ? ? ? ? ? ?fprintf(stderr,"Unsupported parityn"); ? ? ? ? ? ?return -1; ? ?} ? ? ? ?/* 設(shè)置停止位*/ ? ?switch (stopbits) ? ?{ ? ? ? ?case 1: ? ? ? ? ? ?options.c_cflag &= ~CSTOPB; ? ? ? ? ? ?break; ? ? ? ?case 2: ? ? ? ? ? ?options.c_cflag |= CSTOPB; ? ? ? ? ? ?break; ? ? ? ?default: ? ? ? ? ? ?fprintf(stderr,"Unsupported stop bitsn"); ? ? ? ? ? ?return -1; ? ?} ? ? ? ?/* Set input parity option */ ? ?if (parity != 'n') ? ? options.c_iflag |= INPCK; ? ?tcflush(fd,TCIFLUSH); ? ?options.c_cc[VTIME] = 150; /* 設(shè)置超時(shí)15 seconds*/ ? ?options.c_cc[VMIN] = 0; ? ?/* Update the options and do it NOW */ ? ?if (tcsetattr(fd,TCSANOW,&options) != 0) ? ?{ ? ? ? ?perror("SetupSerial 3"); ? ? ? ?return -1; ? ?} ? ?return 0; } void str_print(char *buf, int len) { ? ?int i; ? ?for (i=0; i;>

6 FAQ

6.1 UART 調(diào)試打印開關(guān)

6.1.1 通過 debugfs 使用命令打開調(diào)試開關(guān)

注:內(nèi)核需打開 CONFIG_DYNAMIC_DEBUG 宏定義

1.掛載debugfs。 mount -t debugfs none /sys/kernel/debug 2.打開uart模塊所有打印。 echo "module sunxi_uart +p" > /mnt/dynamic_debug/control 3.打開指定文件的所有打印。 echo "file sunxi-uart.c +p" > /mnt/dynamic_debug/control 4.打開指定文件指定行的打印。 echo "file sunxi-uart.c line 615 +p" > /mnt/dynamic_debug/control 5.打開指定函數(shù)名的打印。 echo "func sw_uart_set_termios +p" > /mnt/dynamic_debug/control 6.關(guān)閉打印。 把上面相應(yīng)命令中的+p 修改為-p 即可。 更多信息可參考linux 內(nèi)核文檔:linux-3.10/Documentation/dynamic-debug-howto.txt。

6.1.2 代碼中打開調(diào)試開關(guān)

1.定義CONFIG_SERIAL_DEBUG宏。 linux-4.9 內(nèi)核版本中默認(rèn)沒有定義CONFIG_SERIAL_DEBUG , 需要自行在 drivers/tty/serial/Kconfig 中添加CONFIG_SERIAL_DEBUG 定義,然后drivers/tty/serial/Makefile文件中添加代碼ccflags-$(CONFIG_SERIAL_DEBUG) := -DDEBUG。 注:使用該宏,需要內(nèi)核關(guān)閉CONFIG_DYNAMIC_DEBUG宏。

6.1.3 sysfs 調(diào)試接口

UART 驅(qū)動(dòng)通過 sysfs 節(jié)點(diǎn)提供了幾個(gè)在線調(diào)試的接口

1./sys/devices/platform/soc/uart0/dev_info cupid-p2:/ # cat /sys/devices/platform/soc/uart0/dev_info id = 0 name = uart0 irq = 247 io_num = 2 port->mapbase = 0x0000000005000000 port->membase = 0xffffff800b005000 port->iobase = 0x00000000 pdata->regulator = 0x (null) pdata->regulator_id = 從該節(jié)點(diǎn)可以看到uart端口的一些硬件資源信息。 2./sys/devices/platform/soc/uart0/ctrl_info cupid-p2:/ # cat /sys/devices/platform/soc/uart0/ctrl_info ier : 0x05 lcr : 0x13 mcr : 0x03 fcr : 0xb1 dll : 0x0d dlh : 0x00 last baud : 115384 (dl = 13) TxRx Statistics: tx : 61123 rx : 351 parity : 0 frame : 0 overrun: 0 此節(jié)點(diǎn)可以打印出軟件中保存的一些控制信息,如當(dāng)前UART 端口的寄存器值、收發(fā)數(shù)據(jù)的統(tǒng)計(jì)等。 3./sys/devices/platform/soc/uart0/status cupid-p2:/ # cat /sys/devices/platform/soc/uart0/status uartclk = 24000000 The Uart controller register[Base: 0xffffff800b005000]: [RTX] 0x00 = 0x0000000d, [IER] 0x04 = 0x00000005, [FCR] 0x08 = 0x000000c1 [LCR] 0x0c = 0x00000013, [MCR] 0x10 = 0x00000003, [LSR] 0x14 = 0x00000060 [MSR] 0x18 = 0x00000000, [SCH] 0x1c = 0x00000000, [USR] 0x7c = 0x00000006 [TFL] 0x80 = 0x00000000, [RFL] 0x84 = 0x00000000, [HALT] 0xa4 = 0x00000002 此節(jié)點(diǎn)可以打印出當(dāng)前UART 端口的一些運(yùn)行狀態(tài)信息,包括控制器的各寄存器值。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1372

    瀏覽量

    40275
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8575

    瀏覽量

    151014
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11292

    瀏覽量

    209322
  • uart
    +關(guān)注

    關(guān)注

    22

    文章

    1235

    瀏覽量

    101352
  • 開發(fā)指南
    +關(guān)注

    關(guān)注

    0

    文章

    34

    瀏覽量

    7538
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    EAC0945 linux開發(fā)指南

    EAC0945 linux開發(fā)指南
    發(fā)表于 09-28 12:40

    EAC0945 linux開發(fā)指南

    `EAC0945 linux開發(fā)指南`
    發(fā)表于 10-31 12:18

    Rockchip Linux SDK uboot logo開發(fā)指南

    arm嵌入式vs-rk3399 板卡uboot logo 開發(fā)指南概述:本文檔主要介紹 rockchip linux sdk uboot logo 顯示的相關(guān)功能、配置以及開發(fā)過程中的注意事項(xiàng)。適用于 rockhip
    發(fā)表于 10-09 08:12

    CPLD FPGA高級(jí)應(yīng)用開發(fā)指南

    CPLD FPGA高級(jí)應(yīng)用開發(fā)指南
    發(fā)表于 04-15 10:56 ?58次下載
    CPLD FPGA高級(jí)應(yīng)用<b class='flag-5'>開發(fā)指南</b>

    Tiny6410 Linux開發(fā)指南詳解

    Tiny6410 Linux 開發(fā)指南
    發(fā)表于 07-08 17:12 ?210次下載
    Tiny6410 <b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)指南</b>詳解

    A64開發(fā)板LCD開發(fā)指南

    A64開發(fā)板LCD開發(fā)指南,驅(qū)動(dòng)開發(fā)指南
    發(fā)表于 06-21 17:02 ?0次下載

    彩光燈開發(fā)指南

    彩光燈開發(fā)指南
    發(fā)表于 12-29 20:15 ?0次下載

    Linux的平臺(tái)下Mini210S裸機(jī)程序開發(fā)指南

    Linux的平臺(tái)下Mini210S裸機(jī)程序開發(fā)指南
    發(fā)表于 10-29 10:52 ?59次下載
    <b class='flag-5'>Linux</b>的平臺(tái)下Mini210S裸機(jī)程序<b class='flag-5'>開發(fā)指南</b>

    Rockchip Linux SDK的開發(fā)指南的詳細(xì)資料說明

    本文檔的主要內(nèi)容詳細(xì)介紹的是Rockchip Linux SDK的開發(fā)指南的詳細(xì)資料說明。
    發(fā)表于 01-10 17:17 ?74次下載
    Rockchip <b class='flag-5'>Linux</b> SDK的<b class='flag-5'>開發(fā)指南</b>的詳細(xì)資料說明

    迅為RK3399開發(fā)板嵌入式linux開發(fā)指南

    迅為RK3399開發(fā)板嵌入式linux開發(fā)指南迅為RK3399開發(fā)板發(fā)布《北京迅為嵌入式linux開發(fā)指
    發(fā)表于 11-01 16:58 ?77次下載
    迅為RK3399<b class='flag-5'>開發(fā)</b>板嵌入式<b class='flag-5'>linux</b><b class='flag-5'>開發(fā)指南</b>

    nRF52832開發(fā)指南-下冊(cè)

    nRF52832開發(fā)指南-下冊(cè)
    發(fā)表于 06-16 14:14 ?44次下載

    Tina_Linux_系統(tǒng)軟件開發(fā)指南

    Tina_Linux_系統(tǒng)軟件開發(fā)指南
    的頭像 發(fā)表于 03-02 15:25 ?1818次閱讀
    Tina_<b class='flag-5'>Linux</b>_系統(tǒng)軟件<b class='flag-5'>開發(fā)指南</b>

    Tina Linux配置開發(fā)指南

    Tina Linux配置開發(fā)指南
    的頭像 發(fā)表于 03-02 15:28 ?1.6w次閱讀
    Tina <b class='flag-5'>Linux</b>配置<b class='flag-5'>開發(fā)指南</b>

    Linux NOR開發(fā)指南

    Linux NOR開發(fā)指南
    的頭像 發(fā)表于 03-06 09:55 ?954次閱讀
    <b class='flag-5'>Linux</b> NOR<b class='flag-5'>開發(fā)指南</b>

    【北京迅為】itop-龍芯2k1000開發(fā)指南Linux基礎(chǔ)入門vim 編輯器

    【北京迅為】itop-龍芯2k1000開發(fā)指南Linux基礎(chǔ)入門vim 編輯器
    的頭像 發(fā)表于 10-25 14:56 ?299次閱讀
    【北京迅為】itop-龍芯2k1000<b class='flag-5'>開發(fā)指南</b><b class='flag-5'>Linux</b>基礎(chǔ)入門vim 編輯器
    RM新时代网站-首页