1 前言
CH9434是一款SPI轉四串口轉接芯片,提供四組全雙工的9線異步串口,用于單片機/嵌入式/安卓系統擴展異步串口。提供25路GPIO,以及支持RS485收發控制引腳TNOW。本篇基于STM32MP157處理器平臺,介紹CH9434在嵌入式Linux系統/安卓系統的驅動移植和使用方法。
CH9434相關資料下載鏈接:
CH9434評估板設計原理圖,單片機端操作例程,LINUX驅動及應用例程下載
2 驅動移植流程
2.1 移植準備
1、配置系統SPI設備信息,若支持DTS設備樹可以直接在DTS文件中直接定義此SPI結構體信息,如下所示:
&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>;
};
};
對于不支持DTS設備樹的系統,則需要在board源文件中定義spi0_board_info對象,如下所示:
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中斷引腳,確認CH9434芯片INT中斷請求引腳所連接的CPU的IO口編號,此IO需支持中斷功能。此編號可以直接在驅動源碼ch9434.c中直接指定,也可以在如上SPI設備結構體中指定,如步驟1所示。
此外,注意有些平臺上中斷申請方式可能與驅動中默認實現方式不同,此時需修改ch9434.c文件中ch943x_spi_probe的相關代碼
注:默認情況下請不要修改uart時鐘,若確實需修改以支持部分非標波特率,可在ch943x_probe中修改:
freq = 32 *1000000 *15 / clkdiv;
2.2 靜態編譯驅動
(1)將驅動程序拷貝到內核目錄:$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)運行make menuconfig,選擇驅動/tty/serial下的ch9434 serial support,然后保存配置。
(5)重新編譯系統
2.3 動態編譯驅動—方式1
(1)拷貝驅動文件至用于添加驅動的package/kernel目錄下
(2)新建模塊目錄,如:ch9434,然后添加相關的Makefile和Kconfig文件,通常可以從系統已有的其他驅動下拷貝然后修改
(3)運行“make menuconfig”然后選中“ ch9434 serial support”作為“modules”項
(4)單獨編譯模塊,命令為:
make package/kernel/ch9434/compile V=s
2.4 動態編譯驅動—方式2
拷貝驅動文件至宿主機工作目錄,在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
注意:此方式需系統下提前配置交叉編譯工具鏈,在如上Makefile文件中修改KERN_DIR為已編譯的內核目錄。同時設置環境變量如下:
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目錄下直接執行make,成功時可生成ch9434.ko驅動模塊。
3 加載驅動并驗證
3.1 加載驅動
[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 查看串口節點
進入/dev目錄,可以看到出現ttyWCH0、ttyWCH1、ttyWCH2和ttyWCH3設備節點,表示加載成功。
[root@100ask:/dev]# ls ttyWCH*
ttyWCH0 ttyWCH1 ttyWCH2 ttyWCH3
3.3 驗證SPI通訊
ch943x_probe中會自動調用ch943x_scr_test接口,向4個串口的SPR寄存器分別寫入0x55和0x66并讀取寄存器值,若讀取與寫入的數值相匹配,則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;
}
使用前需在驅動程序中定義宏:
#define DEBUG
#define VERBOSE_DEBUG
以及修改printk內核打印等級:
[root@100ask:~]# echo 8 4 1 7 > /proc/sys/kernel/printk
加載驅動后查看內核打印信息:
[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 驗證IO中斷功能
驅動程序處理串口數據的發送,接收以及Modem輸入中斷事件均是在中斷服務函數中進行,因此當SPI接口正常串口功能不正常,需檢查中斷功能是否正常,當執行串口發送時,驅動會自動打開串口發送中斷(IETHRE),芯片的INT引腳會輸出低電平請求CPU中斷。在打開調試開關時,正常情況下可觀察到中斷服務函數運行的打印信息。此外,也可以手動給CPU的IO口拉高/拉低,測試中斷是否能正常應。
4 功能測試
編譯demo目錄下tty_test_ch9434.c得到可執行目標程序app,運行演示:
./app -D /dev/ttyWCH0 -S 115200 -v
//參數含義
-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 串口收發
(1)串口發送數據流程為:應用軟件調用write方法—>驅動接收請求并將數據拷貝至串口circ_buf,打開串口發送空中斷(IER寄存器IETHRE位)->執行中斷服務函數->判斷為發送空中斷時執行ch943x_handle_tx函數,從circ_buf中拷貝數據,通過SPI發送函數,將數據寫入到串口發送FIFO寄存器->發送完成再次觸發空中斷,當circ_buf仍有數據則繼續發送,否則關閉發送空中斷。
(2)串口接收數據流程為:芯片RXD引腳收到串口數據后->執行中斷服務函數->判斷IIR中斷類型為接收數據超時或接收數據可用時執行ch943x_handle_rx函數->讀取FIFO長度,通過SPI讀取函數,從串口接收FIFO寄存器讀取數據并拷貝至串口circ_buf->退出中斷->通過應用層有數據可讀,應用軟件調用read方法讀數據。
串口收發流程圖:
?
通過串口向PC收發數據測試:
串口發送0x00-0xFF/接收0x61-0x64
?
4.2 使用MODEM功能
引腳介紹:
?
編輯
MODEM輸出測試方法: 程序中設置MODEM信號輸出后,可以直接用萬用表測試信號電壓,也可以將9434評估板串口的輸出引腳連接USB轉串口模塊(如CH342)的MODEM輸入引腳,CH342的USB端連接PC;打開串口調試工具,通斷發送端連接,接收端可觀察數據變化。
?
MODEM輸入測試方法:
進入開發板系統,由PC端串口輸出,調試工具中開啟DTR和RTS,CH9434串口輸入:
?
接收端運行應用程序,輸入“g”獲取modem狀態:
[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 將自動進行硬件流控。芯片將自動根據 FIFO 大小對流控引腳進行操作。啟用自動流控后,CTS 有效時芯片串口將連續發送數據,CTS 引腳無效時,串口最多發送8 字節數據后停止發送。RTS 在觸發 FIFO 達到設定的流控字節數目后自動失效。
FCR 寄存器的 RECVTG1 和 RECVTG0 位用于設置接收 FIFO 的中斷和硬件流控制的觸發點,00 對應256 個字節,即接收滿256 個字節產生接收數據可用的中斷,并在使能硬件流控制時自動無效 RTS 引腳,01 對應512 個字節,10 對應1024 個字節,11 對應1285 個字節。
PC發送端串口工具設置開啟流控制:
?
接收端運行應用程序:
?
4.4 GPIO測試
CH9434 支持部分引腳復用為 GPIO 功能,最多支持25 路,每個 IO 都可以獨立設置方向、上拉電阻和下拉電阻配置。啟用 GPIO 功能后,將自動失效該 IO 其他復用功能。GPIO 功能在設置時需要注意該 IO 原來功能的模式,設置時需要注意 DIR、PD、PU 等 IO 寄存器的順序防止 IO 出現“抖動”。
GPIO輸出測試:
測試方法:以GPIO0為例,該IO默認復用為CTS0;將該IO配置輸出高/低電平,此時默認功能將失效。 添加代碼:
/* 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);
}
使用萬用表查看GPIO0輸出電平 輸出低電平:
?
輸出高電平:
?
GPIO輸入測試:
測試方法:以GPIO11為例,配置為輸入模式,gpioval表示IO值,1個字節表示8個IO,將對應IO交替接地和3.3V引腳,運行應用程序查看輸入值。
測試代碼:
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,輸入高電平時,gpioval應等于11111111B;輸入低電平時,gpioval應等于11110111B 。
測試結果:
GPIO11接地:gpioval = 0xf7
GPIO11接3.3V:gpioval = 0xff
4.5 RS485串口測試
CH9434 串口提供 RS485 切換引腳 TNOW,引腳功能與其他功能復用,當啟用 TNOW 功能后,將自動失效原 MODEM 信號功能。TNOW 還支持極性調節,以適應不同的極性使用場景。
添加代碼:
char rs485 = 1;
ret = libtty_rs485set(fd, rs485);
if (ret != 0) {
printf("libtty_rs485set %s error.
", rs485 ? "enable": "disable");
exit(0);
}
測試方法: 連接CH9434評估板P2和P4(參照原理圖),使用RS485傳輸;連接串口0和串口1對應的RS485引腳(P9和P15),串口0發送0x00~0x0FF,串口1接收顯示:
?
?
審核編輯:湯梓紅
-
單片機
+關注
關注
6035文章
44553瀏覽量
634715 -
嵌入式
+關注
關注
5082文章
19110瀏覽量
304841 -
Linux
+關注
關注
87文章
11295瀏覽量
209348 -
移植
+關注
關注
1文章
379瀏覽量
28124 -
安卓系統
+關注
關注
0文章
273瀏覽量
20555
發布評論請先 登錄
相關推薦
評論