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 = ; pinctrl-1 = ; status = okay; cs-gpios = ; ch9434: ch9434@1 { compatible = wch,ch943x; reg = ; spi-max-frequency = ; interrupt-parent = ; interrupts = ; };};
对于不支持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_ch9434tristate serial_ch9434 serial supportdepends on spiselect serial_corehelp 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 ch9434obj-m += ch9434.o
注意:此方式需系统下提前配置交叉编译工具链,在如上makefile文件中修改kern_dir为已编译的内核目录。同时设置环境变量如下:
export arch=armexport cross_compile=arm-buildroot-linux-gnueabihfexport 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 -vpress 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.gdsr 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 = 0xf7gpio11接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接收显示:
云存储对云视频监控系统有什么好处?
被遗忘的苹果手机iPhone SE,还能有第二代么?
华为以2314件专利授权量位列国内发明第一
移动通信中的智能天线设计介绍
5个冷门且实用的Kubectl使用技巧,99%的人都要知道
CH9434嵌入式Linux与安卓系统驱动移植和使用教程
AB类放大器,AB类放大器是什么意思
Silicon Labs取得ZigBee IP黄金单元认证
华为在业界首实现业务与站点配套智能联动
菲力尔flir one pro查找电路板故障
CISSOID、NAC和Advanced Conversion三强联手开发 高功率密度碳化硅(SiC)逆变器
超声波在医疗领域的应用,医用超声设备的市场规模
利用AV功放自测系统实现音响功能
6P14小型电子管功放的制作,6P14 vacuum tube amplifier
利用超声波传感器在ARM9与linux平台中实现移动机器人导航的设计
12位ADC升级移植内部8位ADC-12-Bit ADC U
dfrobot透明保护壳(兼容乐高积木)简介
新兴记忆体如何处理物联网所创造的机会
电机绕组的磁势讲解
你不一定要买苹果的设备才能听Apple Music