0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于CH347实现USB扩展SPI/I2C/GPIO Master主机应用方案

jf_49670627 来源:jf_49670627 作者:jf_49670627 2023-04-21 15:33 次阅读

​在安卓/Linux主机上经常会遇到CPU原生SPI/I2C/GPIO Master资源通道不够或者功性能不满足实际产品需求的情况,基于USB2.0高速USB转接芯片CH347,配合厂商提供的USB转MPSI(Multi Peripheral Serial Line)Master总线驱动(CH34X-MSPI-Master)可轻松实现为系统扩展SPI和I2C总线、GPIO Expander、中断信号等。

该驱动软件正常工作后,会在系统下创建新的SPI和I2C Master,拥有独立的bus num,原SPI和I2C器件的设备驱动可直接挂载到该总线上,无需任何修改。驱动会同时创建GPIO相关资源,各GPIO可通过sysfs文件系统或应用层软件直接访问,也可以由其他设备驱动申请该GPIO的访问权以及申请GPIO对应中断号并注册中断服务程序。

应用框图:

pYYBAGRCOvWAAefbAAK5hKXjgI0005.png

CH347是一款高速USB总线转接芯片,通过USB总线提供异步串口、I2C同步串行接口、SPI同步串行接口和JTAG接口等。本方案仅使用到CH347的高速SPI、I2C串行总线,以及GPIO功能,使用串口功能需要单独使用CH343SER串口驱动,使用JTAG功能或SPI和I2C的非总线模式应用可使用CH341PAR多功能USB设备驱动。

驱动特点:

1、支持CH347与CH341总线转接芯片;

2、支持SPI、I2C、GPIO、IRQ等接口和功能扩展;

3、支持SPI、I2C的bus总线号、GPIO编号、IRQ中断号的动态分配以及静态指定;

4、支持自动绑定spi通用设备驱动,创建/dev/spidev*;

驱动概述

该Master驱动支持在Linux/安卓主机上,使用USB转串口/JTAG/SPI/I2C/GPIO转换芯片CH347,和USB转串口/SPI/I2C/GPIO转换芯片CH341。

驱动仅支持SPI/I2C/GPIO接口,该文档主要介绍CH347芯片的相关特性。

CH347 SPI接口

PIN脚 SPI功能脚 GPIO复用脚
5 SCS0 gpio2
9 SCS1 gpio5
6 SCK gpio0
8 MOSI -
7 MISO gpio1

SPI接口特性:

SPI模式0/1/2/3

SPI时钟频率60MHz/30MHz/15MHz/7.5MHz/3.75MHz/1.875MHz/937.5KHz/468.75KHz

MSB/LSB传输

8位/16位传输

2路片选

片选高/低有效

CH347 I2C接口

PIN脚 I2C功能脚 GPIO复用脚
11 SCL gpio3
12 SDA -

CH347支持4种I2C时钟:20kHz,100kHz,400kHz和750kHz。该驱动会默认将I2C的时钟初始化为100KHz,当前不支持动态修改该时钟频率,若需要修改可以在ch34x_mpsi_i2c_init函数中修改。

在Linux上增加对器件的驱动支持十分方便,只需要将该器件的设备驱动绑定到此Master驱动生成的总线下即可。举例:

modprobe bmi160_i2c
echo "bmi160 0x68" > /sys/bus/i2c/devices/i2c-$DEV/new_device

modprobe tcs3472
echo "tcs3472 0x29" > /sys/bus/i2c/devices/i2c-$DEV/new_device

驱动创建的I2C设备文件在/sys/bus/i2c/devices/i2c-$DEV/ 目录下

CH347 GPIO接口

PIN脚 GPIO复用脚
15 gpio4
2 gpio6
13 gpio7

CH347的硬件接口支持GPIO0~GPIO7,考虑到部分引脚被SPI和I2C的接口占用了,此驱动仅开放支持了GPIO4,GPIO6和GPIO7。

驱动操作说明

  • 使用“make”或者其他方式编译此驱动,如果动态编译成功会生成“ch34x_mpsi_master.ko”驱动模块
  • 使用“sudo make load”或“sudo insmod ch34x_mpsi_master.ko”动态加载驱动,使用此方式加载SPI总线号和GPIO起始序号会自动分配,也可以通过增加参数进行指定。
  • 如:“sudo insmod ch34x_mpsi_master.ko spi_bus_num=3 gpio_base_num=60”
  • 使用“sudo make unload”或“sudo rmmod ch34x_mpsi_master.ko”卸载驱动
  • 使用“sudo make install”将驱动开机自动工作
  • 使用“sudo make uninstall”卸载该驱动

使用此驱动,需要确认CH347/CH341已经插入主机并且工作正常,可以使用“lsusb”或“dmesg”指令来确定,CH347/CH341的厂商VID是0x1A86。

如果芯片工作正常,可以使用“ls /sys/class/master”,“ls /sys/class/gpio”指令确认设备节点路径。

用户空间访问

使用SPI接口

一旦驱动加载成功,默认会提供2个关联到这个新的SPI Bus的SPI Slave设备,以CH347为例:

/dev/spidev0.0
/dev/spidev0.1

根据设备名称规则 /dev/spidev.,是驱动自动选择的总线号, 是芯片指定引脚的片选信号。

自linux内核5.15开始绑定到spidev驱动需要主动bind使/dev目录下设备可用,如bus 0下slave 1:

# echo spidev > /sys/class/spi_master/spi0/spi0.1/driver_override
# echo spi0.1 > /sys/bus/spi/drivers/spidev/bind

对所有ch34x_mpsi_master驱动管理的设备:

# for i in /sys/bus/usb/drivers/mpsi-ch34x/*/spi_master/spi*/spi*.*; do echo spidev > $i/driver_override; echo $(basename $i) > /sys/bus/spi/drivers/spidev/bind; done

标准I/O函数如 open, ioctl 和close 可以直接和该spi slave进行通讯,打开SPI设备:

int spi = open("/dev/spidev0.0", O_RDWR));

设备打开成功后,可以使用 ioctl函数修改SPI配置和传输数据等。

uint8_t mode = SPI_MODE_0;
uint8_t lsb = SPI_LSB_FIRST;
...
ioctl(spi, SPI_IOC_WR_MODE, &mode);
ioctl(spi, SPI_IOC_WR_LSB_FIRST, &lsb);

函数 ioctl传输数据示例:

uint8_t *mosi; // output data
uint8_t *miso; // input data
...
// fill mosi with output data
...
struct spi_ioc_transfer spi_trans;
memset(&spi_trans, 0, sizeof(spi_trans));
​
spi_trans.tx_buf = (unsigned long) mosi;
spi_trans.rx_buf = (unsigned long) miso;
spi_trans.len = len;
​
int status = ioctl (spi, SPI_IOC_MESSAGE(1), &spi_trans);
​
// use input data in miso

挂载SPI NOR FLASH作为MTD存储设备

举例:flash器件挂载到bus 0 chip 0(spi0.0)

# echo spi0.0 > /sys/bus/spi/drivers/spidev/unbind
# echo spi-nor > /sys/bus/spi/devices/spi0.0/driver_override
# echo spi0.0 > /sys/bus/spi/drivers/spi-nor/bind

注:为方便用户使用,该驱动默认会创建spidev设备,用户可以使用上面的命令主动解绑与spidev的绑定,或者undefine在ch34x_mpsi_master_spi.c文件中的“SPIDEV”宏定义。

使用GPIO接口

用户空间方位GPIO,可以使用sysfs,对驱动支持的GPIO,可在如下系统目录下查看。

/sys/class/gpio/

是定义在驱动变量 ch347_board_config中的GPIO名称 ,目录包含

  • value 文件用于配置或读取GPIO电平
  • edge文件用于配置GPIO中断使能以及中断类型
  • direction文件用于改变支持双向GPIO的引脚方向

注:对文件的读写操作,用户需要指定的读写权限。

当前支持的中断类型包括:

  • rising 上升沿中断
  • falling 下降沿中断
  • both 双边沿中断

打开GPIO

使用GPIO前,需要先打开value文件

int  fd;
​
if ((fd = open("/sys/class/gpio/value", O_RDWR)) == -1) 
{
   perror("open");
   return -1;
}

是GPIO的名称

设置GPIO方向

配置GPIO方向为input或output,可在root权限下简单地写入in或out字符串到direction文件。

echo out > /sys/class/gpio/gpio4/direction

设置GPIO输出

文件value打开后,可使用标准I/O函数进行读写,配置GPIO输出电平,可简单使用write函数,写入后GPIO会立刻输出指定电平。

if (write(fd, value ? "1" : "0", 1) == -1) 
{
   perror ("write");
    return -1;
}

读取GPIO电平

读取GPIO电平,可简单使用read函数:

char buf;
​
if (read(fd, &buf, 1) == -1) 
{
   perror("read");
   return -1;
}
​
value = (buf == '0') ? 0 : 1;

每一次读操作后,需要将文件位置指针需要重新定位到首字节。

if (lseek(fd, 0, SEEK_SET) == -1) {
   perror("lseek");
   return -1;
}

使用GPIO中断

完整的使用GPIO中断功能的驱动例程:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
​
#define GPIO_NUMBER 509 /* modify with actual gpio number */
​
static irqreturn_t gpio_interrupt(int irq, void *dev_id)
{
    printk("gpio_interrupt callback.n");
​
    return IRQ_HANDLED;
}
​
static int __init ch34x_gpio_init(void)
{
    unsigned long flags = IRQF_TRIGGER_FALLING;
    int ret;
    int irq;
​
    irq = gpio_to_irq(GPIO_NUMBER);
    printk("irq: %dn", irq);
    ret = gpio_request(GPIO_NUMBER, "gpioint");
    if (ret) {
        printk("gpio_request failed.n");
        goto exit;
    }
    ret = gpio_direction_input(GPIO_NUMBER);
    if (ret) {
        printk("gpio_direction_input failed.n");
        gpio_free(GPIO_NUMBER);
        goto exit;
    }
    irq_set_irq_type(irq, flags);
    ret = request_irq(irq, gpio_interrupt, 0, "gpio_handler", NULL);
    printk("%s - request_irq = %d result = %dn", __func__, irq, ret);
​
exit:
    return ret;
}
​
static void __exit ch34x_gpio_exit(void)
{
    int irq;
​
    irq = gpio_to_irq(GPIO_NUMBER);
    free_irq(irq, NULL);
    gpio_free(GPIO_NUMBER);
    printk("gpio driver exit.n");
}
​
module_init(ch34x_gpio_init);
module_exit(ch34x_gpio_exit);
​
MODULE_LICENSE("GPL");
​

注:该驱动默认会创建gpio设备,若需要在内核中使用中断功能,需要undefine在ch34x_mpsi_master_gpio.c中定义的“SYSFS_GPIO”宏。

CH341支持3种工作模式

模式0: [串口]

模式1: [SPI+ I2C + GPIO]

模式2: [打印口]

CH347支持4种模式

模式0: [串口* 2] VCP/CDC 驱动模式

模式1: [SPI + I2C + 串口* 1] VCP 驱动模式

模式2: [SPI + I2C + 串口* 1] HID 驱动模式

模式3: [JTAG + 串口* 1] VCP 驱动模式

该驱动只可工作在 ch341 模式1ch347 模式1

有技术问题,可以发邮件至技术邮箱: tech@wch.cn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • usb
    usb
    +关注

    关注

    60

    文章

    7890

    浏览量

    263954
  • Linux
    +关注

    关注

    87

    文章

    11222

    浏览量

    208890
  • 主机
    +关注

    关注

    0

    文章

    986

    浏览量

    35056
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1700

    浏览量

    91301
  • GPIO
    +关注

    关注

    16

    文章

    1196

    浏览量

    51904
收藏 人收藏

    评论

    相关推荐

    GPIO模拟I2C总线的驱动设计与实现

    I2C总线简单方便,是我们经常使用的一种总线。但有时候我们的MCU没有足够多的I2C控制器来实现我们的应用,所幸我可以使用普通的GPIO引脚来模拟低速的
    发表于 12-14 14:19 5325次阅读
    <b class='flag-5'>GPIO</b>模拟<b class='flag-5'>I2C</b>总线的驱动设计与<b class='flag-5'>实现</b>

    南京沁恒微高速USB转接芯片 CH347型号

    CH347是一款高速USB总线转接芯片,通过USB总线提供异步串口、I2C同步串行接口、SPI同步串行接口和JTAG接口等。 在异步串口方式
    发表于 05-16 13:48

    PCA9698 I2C扩展芯片

    PCA9698 是一款40 位I2C 输入/输出扩展器,能够实现I2C/SMBus 应用中40 位GPIO
    发表于 11-10 14:24 88次下载

    I2C I/O扩展芯片特性分析

    简介   I/O口扩展芯片可用于MCU/DSP通用I/O口的扩展,通过I2C扩展
    发表于 07-20 09:54 1.3w次阅读

    EXAR推出基于I2CSPIGPIO扩展芯片

    EXAR 公司近日发布了XRA120x I2C/SMBus GPIO (通用输入/输出 )扩展芯片以及 XRA140x SPI GPIO
    发表于 10-14 09:09 3330次阅读

    沁恒股份USB Android HOST芯片:CH9343概述

     CH9343是一个高度集成、低功耗、单芯片全速USB Android Host接口控制芯片,可配置为6种扩展接口:UART、GPIO、PWM、I2
    的头像 发表于 11-04 14:11 2533次阅读
    沁恒股份<b class='flag-5'>USB</b> Android HOST芯片:<b class='flag-5'>CH</b>9343概述

    STM32 通用GPIO模拟I2C实现

    STM32 模拟I2C实现#通用GPIO模拟I2C通信实现样例1 GPIO初始化``#ifdef
    发表于 11-29 15:21 28次下载
    STM32 通用<b class='flag-5'>GPIO</b>模拟<b class='flag-5'>I2C</b><b class='flag-5'>实现</b>

    详细介绍GPIOI2CSPI通讯原理以及物理层原理

    6. I2C接口工作模式7. 硬件拉高拉低的过程8. 一对多9. 开发流程三. SPI1. 什么是SPI2. SPI优与缺点3.
    发表于 12-05 12:51 21次下载
    详细介绍<b class='flag-5'>GPIO</b>、<b class='flag-5'>I2C</b>、<b class='flag-5'>SPI</b>通讯原理以及物理层原理

    详细介绍GPIOI2CSPI通讯原理以及物理层原理

    6. I2C接口工作模式7. 硬件拉高拉低的过程8. 一对多9. 开发流程三. SPI1. 什么是SPI2. SPI优与缺点3.
    发表于 12-05 13:21 9次下载
    详细介绍<b class='flag-5'>GPIO</b>、<b class='flag-5'>I2C</b>、<b class='flag-5'>SPI</b>通讯原理以及物理层原理

    高速USB总线转接芯片CH347概述、特点及封装

    CH347是一款高速USB总线转接芯片,通过USB总线提供异步串口、I2C同步串行接口、SPI同步串行接口和JTAG接口等。
    的头像 发表于 06-28 10:33 3664次阅读
    高速<b class='flag-5'>USB</b>总线转接芯片<b class='flag-5'>CH347</b>概述、特点及封装

    高速USB转接芯片CH347技术手册

    电子发烧友网站提供《高速USB转接芯片CH347技术手册.pdf》资料免费下载
    发表于 09-09 15:29 7次下载
    高速<b class='flag-5'>USB</b>转接芯片<b class='flag-5'>CH347</b>技术手册

    Gowin I2C Master/Slave用户指南

    Gowin I2C Master 和 Slave 用户指南主要包括功能简介、信号定义、工 作原理、实例化等,旨在帮助用户快速了解 Gowin I2C Master IP 和 Slav
    发表于 09-15 10:07 1次下载
    Gowin <b class='flag-5'>I2C</b> <b class='flag-5'>Master</b>/Slave用户指南

    高速USB转接芯片沁恒CH347介绍

    高速USB转接芯片沁恒CH347-国内唯一USBSPIUSBI2C
    发表于 10-10 16:25 1606次阅读
    高速<b class='flag-5'>USB</b>转接芯片沁恒<b class='flag-5'>CH347</b>介绍

    高速USB转接芯片 CH347

    CH347 是一款高速 USB 总线转接芯片,通过 USB 总线提供异步串口、I2C 同步串行接口、SPI 同 步串行接口和 JTAG 接口
    的头像 发表于 04-28 11:27 2827次阅读
    高速<b class='flag-5'>USB</b>转接芯片 <b class='flag-5'>CH347</b>

    探索GPIO/ADC/LED/I2C/SPI/USB…的完整世界

    今天了解的是GPIO/ADC/LED/I2C/SPI/USB硬件接口设计及其注意事项,希望对大家有所帮助。
    的头像 发表于 11-17 09:59 161次阅读
    探索<b class='flag-5'>GPIO</b>/ADC/LED/<b class='flag-5'>I2C</b>/<b class='flag-5'>SPI</b>/<b class='flag-5'>USB</b>…的完整世界