一、fusb302介绍
Fusb302是可编程的USB Type-C控制器,支持识别各种USB 设备和对应的状态;且支持最高100W的PD协议。
Fusb302用CC1/CC2引脚与typeC电源适配器通信,通过PD协议来设置电源适配器的输出电压和电流,从而达到控制充电电压电流,实现快充的目的。
说白了,就是通过 PD协议 控制电源适配器,从VBUS输出不同功率的电源(最高100W)。
二、fusb302引脚功能
引脚 |
功能 |
CC1/CC2 |
主要用来 PD协议通信 或 其他: 1)探测USB连接,区分正反面,区分DFP和UFP的主从关系 2)配置Vbus,有USB Type-C和USB Power Delivery两种模式 3)配置Vconn,当线缆里有芯片的时候,一个cc传输信号,一个cc变成供电Vconn,用来给线缆里的芯片供电(3.3V或5V); 4)如果CC通道连接其他配置,如连接音频配件、DP、PCIE时,CC通道配置是不同的。 |
VBUS |
VBUS为电源适配器提供的用来给电池充电的总线电源,USB PD协议可配置电压和电流,最大100W,如:20V 5A |
VCONN |
当线缆里有芯片的时候,一个cc传输信号,一个cc变成供电Vconn,用来给线缆里的芯片供电(3.3V或5V) |
INIT_N |
中断输出,当有事件发生时,用于通知处理器读取I2C寄存器数据。如:插入/拔出typeC,INIT_N都会拉低一下。 |
SCL、SDA |
I2C时钟、数据引脚 |
介绍:
1、主从
SRC:Source,供电端如:充电器。
SNK:Sink,受电端如:手电筒。
2、DFP、UFP、DRP用途解析
① DFP:Source,下行端口,可以理解为一个Host,DFP作为source给VBUS和vcon供电的,简单理解为一个提供电源的设备,如:电源适配器。
② UFP:Sink,上行端口,可以理解为Device,UFP可以理解为受电端口,DFP为供电端口,UFP从VBUS中取电,并可提供数据。典型设备如:U盘、移动硬盘。
③ DRP:双角色端口,DRP既可以做DFP(Source)又可以做UFP(Sink),也可以在DFP和UFP间动态切换,典型设备是:笔记本电脑、充电宝。
充电宝为UFP(Sink)的应用:电源适配器给充电宝充电。
充电宝为DFP(Source)的应用:充电宝给手机或其他设备充电。
三、fusb302驱动移植及修改方法
与供应商沟通,原厂前期只提供了mcu的代码没提供linux的。因此移植瑞芯微的板子里的fusb302驱动到酷芯平台。
1、将fusb302驱动编译成.ko,并加载
1)设备树dts添加子节点,fusb302挂载 i2c3上
&i2c3 {
status = "okay";
fusb0:fusb30x@22 {
compatible = "fairchild,fusb302";
reg = <0x22>; //设备地址
int-n-gpios = <&porta0 4 GPIO_ACTIVE_HIGH>; //GPIO_A0_4
status = "okay";
};
};
引脚配置如下:
i2c 和 gpio 引脚
2)Makefile
KERN_DIR = /home/dongao/share/kernel/linux-linaro-stable-lsk-v4.9-17.07 #内核路径
all:
make -C $(KERN_DIR) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=`pwd` modules
clean:
make -C $(KERN_DIR) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=`pwd` modules clean
rm -rf modules.order
obj-m += fusb302.o
3)加载并测试
删除没有定义的 extcon相关函数。
$ make //ubuntu下编译生成 fusb302.ko
$ insmod fusb302.ko //ARM板加载驱动
发现问题:
问题1:probe() 中的 devm_extcon_dev_allocate() 函数会失败。
解决方法:内核配置 extcon。
问题2:酷芯提供的内核的 drivers\extcon\extcon.c 中的 extcon_info[] 没有定义 EXTCON_USB_VBUS_EN
解决方法:按照rk内核的extcon.c文件,extcon_info[]数组添加 EXTCON_USB_VBUS_EN 如下。
struct __extcon_info {
unsigned int type;
unsigned int id;
const char *name;
} extcon_info[] = {
...
/* 2022-08-22 donga add */
[EXTCON_USB_VBUS_EN] = {
.type = EXTCON_TYPE_USB,
.id = EXTCON_USB_VBUS_EN,
.name = "USB_VBUS_EN",
},
...
}
问题3:正常运行probe()后,插上typec电源适配器后,发现电源适配器不停的发送 Hard Rest。
分析原因:PD协议对实时性要求比较高,fusb302收到适配器适配器的cap自动返回GoodCRC之后,要在15ms内发送request,不然电源适配器会发送HardReset命令。rk平台主频高,每个打印信息也只消耗1ms左右,而酷芯为900M主频,每个打印信息都间隔10ms左右。因此没来得及发送request。
解决方法:见修改驱动源码。
借用一张网图,描述PD协议交互过程:
2、修改驱动源码
修改方向:发送完GoodCRC后,会触发 INTERRUPTB_GCRCSENT 中断,状态机中尽量减少不需要的分支。
之后,经过多次HardRest,某次及时request进入正常充电。(此时代码不稳定,我想要每次都能立刻request进入正常充电)。继续调试代码。
同时,测试typeC拔出时,应该能产生INIT_N中断。示波器测INIT_N脚,确实有拉低的动作,奇怪为什么没有运行中断处理函数?
原因:驱动代码中断配置成 IRQF_ONESHOT | IRQF_TRIGGER_LOW 模式,中断处理函数中关中断,工作队列再开中断。之后就无法触发了。(如果不关开中断,可以一直触发)。这个问题找厂家协助处理中。。。
测试发现下降沿触发不会出现这样的问题,因此对代码作出修改,改为 IRQF_TRIGGER_FALLING 模式加载驱动时,还需判断 type-C插入状态。
如下:
3、验证fusb302驱动,结合bq25720 充电管理IC
fusb302只是控制typeC电源适配器的VBUS脚输入的电压和电流。充电还需要充电管理IC,这里为 bq25720(驱动方法看相关文档)。
如:项目中fusb302控制电压适配器VBUS输出为 9V 3A,再通过 bq25720 限制到 8V 2A(实际看功率,要比VBUS的功率小),最终给电池充电。
硬件环境:
PD快充流程:
1)fusb302 原理图
2)加载驱动
$ insmod fusb302.ko //ARM板加载fusb302.ko驱动
$ insmod bq25720_charger.ko //ARM板加载bq25720_charger.ko驱动
3)逻辑分析仪采集CC1/2 PD协议通信过程
Sink发送Soft_Rest信号
Sink请求
至此,每次插上type-c充电时,电流计能检测到 9V 2.2A左右。与我代码里设置的值一致。文章来源:https://www.toymoban.com/news/detail-447076.html
附上源码:https://download.csdn.net/download/hinewcc/87589264文章来源地址https://www.toymoban.com/news/detail-447076.html
到了这里,关于PD快充 - fusb302驱动调试笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!