1 前言
CH9434是一款SPI轉(zhuǎn)四串口轉(zhuǎn)接芯片,提供四組全雙工的9線異步串口,用于單片機(jī)/嵌入式/安卓系統(tǒng)擴(kuò)展異步串口。提供25路GPIO,以及支持RS485收發(fā)控制引腳TNOW。本篇基于STM32MP157處理器平臺(tái),介紹CH9434在嵌入式Linux系統(tǒng)/安卓系統(tǒng)的驅(qū)動(dòng)移植和使用方法。
CH9434相關(guān)資料下載鏈接:
CH9434評(píng)估板設(shè)計(jì)原理圖,單片機(jī)端操作例程,LINUX驅(qū)動(dòng)及應(yīng)用例程下載
2 驅(qū)動(dòng)移植流程
2.1 移植準(zhǔn)備
1、配置系統(tǒng)SPI設(shè)備信息,若支持DTS設(shè)備樹(shù)可以直接在DTS文件中直接定義此SPI結(jié)構(gòu)體信息,如下所示:
&spi5 {
pinctrl-names = "default","sleep";
pinctrl-0 = <&spi5_pins_a>;
pinctrl-1 = <&spi5_sleep_pins_a>;
status = "okay";
cs-gpios = <&gpioz 4 GPIO_ACTIVE_LOW>;
?
ch9434: ch9434@1 {
compatible = "wch,ch943x";
reg = <0>;
spi-max-frequency = <3000000>;
interrupt-parent = <&gpiod>;
interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
};
};
對(duì)于不支持DTS設(shè)備樹(shù)的系統(tǒng),則需要在board源文件中定義spi0_board_info對(duì)象,如下所示:
static struct spi_board_info spi0_board_info[] __initdata = {
{
.modalias = "ch943x_spi",
.platform_data = NULL,
.max_speed_hz = 3000000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data = &spi0_csi[0],
.irq = IRQ_EINT(8),
}
};
2、配置IO中斷引腳,確認(rèn)CH9434芯片INT中斷請(qǐng)求引腳所連接的CPU的IO口編號(hào),此IO需支持中斷功能。此編號(hào)可以直接在驅(qū)動(dòng)源碼ch9434.c中直接指定,也可以在如上SPI設(shè)備結(jié)構(gòu)體中指定,如步驟1所示。
此外,注意有些平臺(tái)上中斷申請(qǐng)方式可能與驅(qū)動(dòng)中默認(rèn)實(shí)現(xiàn)方式不同,此時(shí)需修改ch9434.c文件中ch943x_spi_probe的相關(guān)代碼
注:默認(rèn)情況下請(qǐng)不要修改uart時(shí)鐘,若確實(shí)需修改以支持部分非標(biāo)波特率,可在ch943x_probe中修改:
freq = 32 *1000000 *15 / clkdiv;
2.2 靜態(tài)編譯驅(qū)動(dòng)
(1)將驅(qū)動(dòng)程序拷貝到內(nèi)核目錄:$kernel_srcdrivers tyserial
(2)向$kernel_srcdrivers tyserialKonfig 中添加:
config SERIAL_CH9434
tristate "SERIAL_CH9434 serial support"
depends on SPI
select SERIAL_CORE
help
This selects support for ch9434 serial ports.
(3)向$kernel_srcdrivers tyserialMakefile 中添加:
obj-$(CONFIG_SERIAL_CH943X)+= ch9434.o
(4)運(yùn)行make menuconfig,選擇驅(qū)動(dòng)/tty/serial下的ch9434 serial support,然后保存配置。
(5)重新編譯系統(tǒng)
2.3 動(dòng)態(tài)編譯驅(qū)動(dòng)—方式1
(1)拷貝驅(qū)動(dòng)文件至用于添加驅(qū)動(dòng)的package/kernel目錄下
(2)新建模塊目錄,如:ch9434,然后添加相關(guān)的Makefile和Kconfig文件,通常可以從系統(tǒng)已有的其他驅(qū)動(dòng)下拷貝然后修改
(3)運(yùn)行“make menuconfig”然后選中“ ch9434 serial support”作為“modules”項(xiàng)
(4)單獨(dú)編譯模塊,命令為:
make package/kernel/ch9434/compile V=s
2.4 動(dòng)態(tài)編譯驅(qū)動(dòng)—方式2
拷貝驅(qū)動(dòng)文件至宿主機(jī)工作目錄,在driver目錄下新增Makefile文件,如下所示:
KERN_DIR = /home/Linux-5.4
all:
make -C $(KERN_DIR) M=`pwd` modules
$(CROSS_COMPILE)gcc -o ch9434 ch9434.c
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
rm -f ch9434
obj-m += ch9434.o
注意:此方式需系統(tǒng)下提前配置交叉編譯工具鏈,在如上Makefile文件中修改KERN_DIR為已編譯的內(nèi)核目錄。同時(shí)設(shè)置環(huán)境變量如下:
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
export PATH=$PATH:/home/xxx/sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
在driver目錄下直接執(zhí)行make,成功時(shí)可生成ch9434.ko驅(qū)動(dòng)模塊。
3 加載驅(qū)動(dòng)并驗(yàn)證
3.1 加載驅(qū)動(dòng)
[root@100ask:/mnt/ch9434]# insmod ch9434.ko
[ 477.091787] ch9434: loading out-of-tree module taints kernel.
[ 477.096776] ch9434: module verification failed: signature and/or required key missing - tainting kernel
[ 477.109272] ch9434: SPI driver for spi to serial chip ch9434, etc.
[ 477.114026] ch9434: V1.00 On 2020.06.17
[ 477.123448] ch943x_spi spi0.1: change to SPI MODE 3!
3.2 查看串口節(jié)點(diǎn)
進(jìn)入/dev目錄,可以看到出現(xiàn)ttyWCH0、ttyWCH1、ttyWCH2和ttyWCH3設(shè)備節(jié)點(diǎn),表示加載成功。
[root@100ask:/dev]# ls ttyWCH*
ttyWCH0 ttyWCH1 ttyWCH2 ttyWCH3
3.3 驗(yàn)證SPI通訊
ch943x_probe中會(huì)自動(dòng)調(diào)用ch943x_scr_test接口,向4個(gè)串口的SPR寄存器分別寫(xiě)入0x55和0x66并讀取寄存器值,若讀取與寫(xiě)入的數(shù)值相匹配,則SPI接口通訊正常。
static int ch943x_scr_test(struct uart_port *port)
{
struct ch943x_port *s = dev_get_drvdata(port->dev);
dev_vdbg(&s->spi_dev->dev,"******Uart %d SPR Test Start******
", port->line);
ch943x_port_write(port, CH943X_SPR_REG,0x55);
ch943x_port_read(port, CH943X_SPR_REG);
ch943x_port_write(port, CH943X_SPR_REG,0x66);
ch943x_port_read(port, CH943X_SPR_REG);
dev_vdbg(&s->spi_dev->dev,"******Uart %d SPR Test End******
", port->line);
return 0;
}
使用前需在驅(qū)動(dòng)程序中定義宏:
#define DEBUG
#define VERBOSE_DEBUG
以及修改printk內(nèi)核打印等級(jí):
[root@100ask:~]# echo 8 4 1 7 > /proc/sys/kernel/printk
加載驅(qū)動(dòng)后查看內(nèi)核打印信息:
[root@100ask:/mnt/ch9434]# insmod ch9434.ko
[ 477.091787] ch9434: loading out-of-tree module taints kernel.
[ 477.096776] ch9434: module verification failed: signature and/or required key missing - tainting kernel
[ 477.109272] ch9434: SPI driver for spi to serial chip ch9434, etc.
[ 477.114026] ch9434: V1.00 On 2020.06.17
[ 477.123448] ch943x_spi spi0.1: change to SPI MODE 3!
[ 477.129197] ch943x_spi spi0.1: ch943x_port_write - reg:0x81, val:0x 0
[ 477.135149] ch943x_spi spi0.1: ch943x_port_write - reg:0x84, val:0x 0
[ 477.141604] ch943x_spi spi0.1: ch943x_port_read - reg:0x 6, val:0x 0
[ 477.148458] ch943x_spi spi0.1: ******Uart 0 SPR Test Start******
[ 477.154347] ch943x_spi spi0.1: ch943x_port_write - reg:0x87, val:0x55
[ 477.160705] ch943x_spi spi0.1: ch943x_port_read - reg:0x 7, val:0x55
[ 477.166982] ch943x_spi spi0.1: ch943x_port_write - reg:0x87, val:0x66
[ 477.173556] ch943x_spi spi0.1: ch943x_port_read - reg:0x 7, val:0x66
[ 477.179305] ch943x_spi spi0.1: ******Uart 0 SPR Test End******
[ 477.185633] ch943x_spi spi0.1: ch943x_port_write - reg:0x91, val:0x 0
[ 477.192274] ch943x_spi spi0.1: ch943x_port_write - reg:0x94, val:0x 0
[ 477.198463] ch943x_spi spi0.1: ch943x_port_read - reg:0x16, val:0x 0
[ 477.209156] ch943x_spi spi0.1: ******Uart 1 SPR Test Start******
[ 477.214381] ch943x_spi spi0.1: ch943x_port_write - reg:0x97, val:0x55
[ 477.225183] ch943x_spi spi0.1: ch943x_port_read - reg:0x17, val:0x55
[ 477.232922] ch943x_spi spi0.1: ch943x_port_write - reg:0x97, val:0x66
[ 477.241444] ch943x_spi spi0.1: ch943x_port_read - reg:0x17, val:0x66
[ 477.246359] ch943x_spi spi0.1: ******Uart 1 SPR Test End******
[ 477.252862] ch943x_spi spi0.1: ch943x_port_write - reg:0xa1, val:0x 0
[ 477.259188] ch943x_spi spi0.1: ch943x_port_write - reg:0xa4, val:0x 0
[ 477.265396] ch943x_spi spi0.1: ch943x_port_read - reg:0x26, val:0x 0
[ 477.272512] ch943x_spi spi0.1: ******Uart 2 SPR Test Start******
[ 477.277949] ch943x_spi spi0.1: ch943x_port_write - reg:0xa7, val:0x55
[ 477.284520] ch943x_spi spi0.1: ch943x_port_read - reg:0x27, val:0x55
[ 477.290761] ch943x_spi spi0.1: ch943x_port_write - reg:0xa7, val:0x66
[ 477.297358] ch943x_spi spi0.1: ch943x_port_read - reg:0x27, val:0x66
[ 477.303202] ch943x_spi spi0.1: ******Uart 2 SPR Test End******
[ 477.309544] ch943x_spi spi0.1: ch943x_port_write - reg:0xb1, val:0x 0
[ 477.315969] ch943x_spi spi0.1: ch943x_port_write - reg:0xb4, val:0x 0
[ 477.322556] ch943x_spi spi0.1: ch943x_port_read - reg:0x36, val:0x 0
[ 477.329200] ch943x_spi spi0.1: ******Uart 3 SPR Test Start******
[ 477.334860] ch943x_spi spi0.1: ch943x_port_write - reg:0xb7, val:0x55
[ 477.341359] ch943x_spi spi0.1: ch943x_port_read - reg:0x37, val:0x55
[ 477.347567] ch943x_spi spi0.1: ch943x_port_write - reg:0xb7, val:0x66
[ 477.354204] ch943x_spi spi0.1: ch943x_port_read - reg:0x37, val:0x66
[ 477.360005] ch943x_spi spi0.1: ******Uart 3 SPR Test End******
[ 477.366257] ch943x_spi spi0.1: ch943x_port_write - reg:0xc8, val:0xcd
[ 477.372805] ch943x_spi spi0.1: ch943x_port_read - reg:0x48, val:0xcd
[ 477.382495] ch943x_spi spi0.1: ch943x_probe - devm_request_threaded_irq =84 result:0
[ 477.392463] cpu cpu0: Looking up cpu-supply from device tree
3.4 驗(yàn)證IO中斷功能
驅(qū)動(dòng)程序處理串口數(shù)據(jù)的發(fā)送,接收以及Modem輸入中斷事件均是在中斷服務(wù)函數(shù)中進(jìn)行,因此當(dāng)SPI接口正常串口功能不正常,需檢查中斷功能是否正常,當(dāng)執(zhí)行串口發(fā)送時(shí),驅(qū)動(dòng)會(huì)自動(dòng)打開(kāi)串口發(fā)送中斷(IETHRE),芯片的INT引腳會(huì)輸出低電平請(qǐng)求CPU中斷。在打開(kāi)調(diào)試開(kāi)關(guān)時(shí),正常情況下可觀察到中斷服務(wù)函數(shù)運(yùn)行的打印信息。此外,也可以手動(dòng)給CPU的IO口拉高/拉低,測(cè)試中斷是否能正常應(yīng)。
4 功能測(cè)試
編譯demo目錄下tty_test_ch9434.c得到可執(zhí)行目標(biāo)程序app,運(yùn)行演示:
./app -D /dev/ttyWCH0 -S 115200 -v
//參數(shù)含義
-D --device tty device to use
-S --speed uart speed
-v --verbose verbose (show rx buffer)
-f --hardflow open hardware flowcontrol
-R --rs485 enable rs485 function
-s --savefile save rx data to file
4.1 串口收發(fā)
(1)串口發(fā)送數(shù)據(jù)流程為:應(yīng)用軟件調(diào)用write方法—>驅(qū)動(dòng)接收請(qǐng)求并將數(shù)據(jù)拷貝至串口circ_buf,打開(kāi)串口發(fā)送空中斷(IER寄存器IETHRE位)->執(zhí)行中斷服務(wù)函數(shù)->判斷為發(fā)送空中斷時(shí)執(zhí)行ch943x_handle_tx函數(shù),從circ_buf中拷貝數(shù)據(jù),通過(guò)SPI發(fā)送函數(shù),將數(shù)據(jù)寫(xiě)入到串口發(fā)送FIFO寄存器->發(fā)送完成再次觸發(fā)空中斷,當(dāng)circ_buf仍有數(shù)據(jù)則繼續(xù)發(fā)送,否則關(guān)閉發(fā)送空中斷。
(2)串口接收數(shù)據(jù)流程為:芯片RXD引腳收到串口數(shù)據(jù)后->執(zhí)行中斷服務(wù)函數(shù)->判斷IIR中斷類(lèi)型為接收數(shù)據(jù)超時(shí)或接收數(shù)據(jù)可用時(shí)執(zhí)行ch943x_handle_rx函數(shù)->讀取FIFO長(zhǎng)度,通過(guò)SPI讀取函數(shù),從串口接收FIFO寄存器讀取數(shù)據(jù)并拷貝至串口circ_buf->退出中斷->通過(guò)應(yīng)用層有數(shù)據(jù)可讀,應(yīng)用軟件調(diào)用read方法讀數(shù)據(jù)。
串口收發(fā)流程圖:
?
通過(guò)串口向PC收發(fā)數(shù)據(jù)測(cè)試:
串口發(fā)送0x00-0xFF/接收0x61-0x64
?
4.2 使用MODEM功能
引腳介紹:
?
編輯
MODEM輸出測(cè)試方法: 程序中設(shè)置MODEM信號(hào)輸出后,可以直接用萬(wàn)用表測(cè)試信號(hào)電壓,也可以將9434評(píng)估板串口的輸出引腳連接USB轉(zhuǎn)串口模塊(如CH342)的MODEM輸入引腳,CH342的USB端連接PC;打開(kāi)串口調(diào)試工具,通斷發(fā)送端連接,接收端可觀察數(shù)據(jù)變化。
?
MODEM輸入測(cè)試方法:
進(jìn)入開(kāi)發(fā)板系統(tǒng),由PC端串口輸出,調(diào)試工具中開(kāi)啟DTR和RTS,CH9434串口輸入:
?
接收端運(yùn)行應(yīng)用程序,輸入“g”獲取modem狀態(tài):
[root@100ask:/mnt/ch9434/demo]# ./app -D /dev/ttyWCH0 -S 115200 -v
press s to set modem, z to clear modem, g to get modem,b to send break, w to write, r to read, q for quit.
g
DSR Active!
CTS Active!
press s to set modem, z to clear modem, g to get modem,b to send break, w to write, r to read, q for quit.
4.3 硬件流控
串口流控功能使能是將 MCR寄存器的AFE位置1,CH9434 將自動(dòng)進(jìn)行硬件流控。芯片將自動(dòng)根據(jù) FIFO 大小對(duì)流控引腳進(jìn)行操作。啟用自動(dòng)流控后,CTS 有效時(shí)芯片串口將連續(xù)發(fā)送數(shù)據(jù),CTS 引腳無(wú)效時(shí),串口最多發(fā)送8 字節(jié)數(shù)據(jù)后停止發(fā)送。RTS 在觸發(fā) FIFO 達(dá)到設(shè)定的流控字節(jié)數(shù)目后自動(dòng)失效。
FCR 寄存器的 RECVTG1 和 RECVTG0 位用于設(shè)置接收 FIFO 的中斷和硬件流控制的觸發(fā)點(diǎn),00 對(duì)應(yīng)256 個(gè)字節(jié),即接收滿256 個(gè)字節(jié)產(chǎn)生接收數(shù)據(jù)可用的中斷,并在使能硬件流控制時(shí)自動(dòng)無(wú)效 RTS 引腳,01 對(duì)應(yīng)512 個(gè)字節(jié),10 對(duì)應(yīng)1024 個(gè)字節(jié),11 對(duì)應(yīng)1285 個(gè)字節(jié)。
PC發(fā)送端串口工具設(shè)置開(kāi)啟流控制:
?
接收端運(yùn)行應(yīng)用程序:
?
4.4 GPIO測(cè)試
CH9434 支持部分引腳復(fù)用為 GPIO 功能,最多支持25 路,每個(gè) IO 都可以獨(dú)立設(shè)置方向、上拉電阻和下拉電阻配置。啟用 GPIO 功能后,將自動(dòng)失效該 IO 其他復(fù)用功能。GPIO 功能在設(shè)置時(shí)需要注意該 IO 原來(lái)功能的模式,設(shè)置時(shí)需要注意 DIR、PD、PU 等 IO 寄存器的順序防止 IO 出現(xiàn)“抖動(dòng)”。
GPIO輸出測(cè)試:
測(cè)試方法:以GPIO0為例,該IO默認(rèn)復(fù)用為CTS0;將該IO配置輸出高/低電平,此時(shí)默認(rèn)功能將失效。 添加代碼:
/* gpio test */
ret = libtty_gpioenable(fd, 0, 1);
if (ret != 0) {
printf("libtty_gpioenable error.
");
exit(0);
}
ret = libtty_gpiopullup(fd, 0, 1);
if (ret != 0) {
printf("libtty_gpiopullup error.
");
exit(0);
}
ret = libtty_gpiodir(fd, 0, 1);
if (ret != 0) {
printf("libtty_gpiodir error.
");
exit(0);
}
ret = libtty_gpioset(fd, 0, 1);
if (ret != 0) {
printf("libtty_gpioset error.
");
exit(0);
}
使用萬(wàn)用表查看GPIO0輸出電平 輸出低電平:
?
輸出高電平:
?
GPIO輸入測(cè)試:
測(cè)試方法:以GPIO11為例,配置為輸入模式,gpioval表示IO值,1個(gè)字節(jié)表示8個(gè)IO,將對(duì)應(yīng)IO交替接地和3.3V引腳,運(yùn)行應(yīng)用程序查看輸入值。
測(cè)試代碼:
ret = libtty_gpioenable(fd, 1, 1);
if (ret != 0)
exit(0);
ret = libtty_gpiopullup(fd, 1, 0);
if (ret != 0)
exit(0);
ret = libtty_gpiodir(fd, 1, 0);
if (ret != 0)
exit(0);
ret = libtty_gpioget(fd, 1, &gpioval);
if (ret != 0)
exit(0);
else
printf("gpioval = 0x%02x
", gpioval);
GPIO11即GPIO1_4,輸入高電平時(shí),gpioval應(yīng)等于11111111B;輸入低電平時(shí),gpioval應(yīng)等于11110111B 。
測(cè)試結(jié)果:
GPIO11接地:gpioval = 0xf7
GPIO11接3.3V:gpioval = 0xff
4.5 RS485串口測(cè)試
CH9434 串口提供 RS485 切換引腳 TNOW,引腳功能與其他功能復(fù)用,當(dāng)啟用 TNOW 功能后,將自動(dòng)失效原 MODEM 信號(hào)功能。TNOW 還支持極性調(diào)節(jié),以適應(yīng)不同的極性使用場(chǎng)景。
添加代碼:
char rs485 = 1;
ret = libtty_rs485set(fd, rs485);
if (ret != 0) {
printf("libtty_rs485set %s error.
", rs485 ? "enable": "disable");
exit(0);
}
測(cè)試方法: 連接CH9434評(píng)估板P2和P4(參照原理圖),使用RS485傳輸;連接串口0和串口1對(duì)應(yīng)的RS485引腳(P9和P15),串口0發(fā)送0x00~0x0FF,串口1接收顯示:
?
?
審核編輯:湯梓紅
-
單片機(jī)
+關(guān)注
關(guān)注
6061文章
44868瀏覽量
646036 -
嵌入式
+關(guān)注
關(guān)注
5133文章
19501瀏覽量
314247 -
Linux
+關(guān)注
關(guān)注
87文章
11446瀏覽量
212628 -
移植
+關(guān)注
關(guān)注
1文章
394瀏覽量
28563 -
安卓系統(tǒng)
+關(guān)注
關(guān)注
0文章
273瀏覽量
20972
發(fā)布評(píng)論請(qǐng)先 登錄
嵌入式移植ch340的教程
如何使用CH9434移植到32單片機(jī)擴(kuò)展4串口
CH9434溢出時(shí)幀數(shù)據(jù)錯(cuò)誤怎么解決?
嵌入式Linux系統(tǒng)開(kāi)發(fā)基礎(chǔ)

嵌入式Linux系統(tǒng)的移植研究
嵌入式Linux系統(tǒng)和驅(qū)動(dòng)開(kāi)發(fā)
【Linux】嵌入式Linux系統(tǒng)的移植(上篇:交叉編譯器、連接方式)

嵌入式linux系統(tǒng)試題庫(kù),嵌入式linux系統(tǒng)移植試題 - 答案

嵌入式Linux系統(tǒng)移植開(kāi)發(fā)-(1)基于Yocto構(gòu)建嵌入式u-boot,內(nèi)核,文件系統(tǒng)

(一)嵌入式linux移植使用ch340

[深度理解嵌入式linux系統(tǒng)移植]深度理解嵌入式linux系統(tǒng)移植
![[深度理解<b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>移植</b>]深度理解<b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>移植</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
四串口芯片CH9434技術(shù)手冊(cè)

基于嵌入式Linux系統(tǒng)的MiniGUI的移植

評(píng)論