前言
DFU状态下的STM32不属于ttyUSB或者ttyACM设备,所以需要用到USB(Universal Serial Bus)的BUS端口,这里记录一下我是如何获取到的BUS口的
准备
我这里用到的设备有
1、BPI-M1+
2、OpenWrt固件(具体配置方法在这里)
3、Artec板子(上面有一片STM32F042F6P6和一片ESP32,我们主要是为了给这2个芯片烧写固件)
4、一个hub(想接更多设备可以接更多hub,但是一定要注意供电,一定要买好点的hub,我在这里遇到了很多供电不足的坑)
我这里用到的软件是hotplug,但是由于hotplug默认配置文件只支持ttyACM和ttyUSB设备,所以需要修改默认的配置文件,配置文件分析可以看这里
区分STM32和ESP32
想要知道设备类型,我们需要输出所有变量
[ "if", [ "eq", "SUBSYSTEM", [ "usb" ] ], [ "exec", "/root/test" ] ]
上面代码是,识别到了usb设备后,执行/root/test这个脚本
然后需要编辑脚本
vi /root/test
将下面的代码放进去
#!/bin/sh echo "==========" >> /tmp/env.log env >> /tmp/env.log echo "----------" >> /tmp/env.log
重启之后将STM32设置为DFU模式,并插入,查看日志
root@OpenWrt:~# cat /tmp/env.log ========== DEVNAME=bus/usb/001/005 ACTION=add SHLVL=1 HOME=/ SEQNUM=1010 BUSNUM=001 MAJOR=189 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MINOR=4 TYPE=0/0/0 DEVNUM=005 PRODUCT=483/df11/2200 PWD=/ DEVTYPE=usb_device ---------- ========== ACTION=add SHLVL=1 HOME=/ SEQNUM=1011 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4/1-1.4:1.0 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MODALIAS=usb:v0483pDF11d2200dc00dsc00dp00icFEisc01ip02in00 TYPE=0/0/0 PRODUCT=483/df11/2200 INTERFACE=254/1/2 PWD=/ DEVTYPE=usb_interface ---------- ========== DEVNAME=bus/usb/001/005 ACTION=bind SHLVL=1 HOME=/ SEQNUM=1012 BUSNUM=001 MAJOR=189 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MINOR=4 DRIVER=usb TYPE=0/0/0 DEVNUM=005 PRODUCT=483/df11/2200 PWD=/ DEVTYPE=usb_device ----------
仔细看会发现,脚本一共触发了三次,根据Tim老师的分析,分别是:1、USB hub插入。2、STM32插入。3、USB hub绑定驱动(由于STM32的DFU设备没有驱动,所以不会触发,如果是CH340这种,还会再触发一次设备驱动绑定)
在这里我们只需加入判断就能识别两种芯片,其中第一个刷的是dfu模式下的STM32,它的PID为df11(PID为固定的,所以可以识别,具体查询地址在这里http://www.linux-usb.org/usb.ids,其中df11代表STM Device in DFU Mode)
输入lsusb命令就能看到PID
Bus 001 Device 012: ID 0483:df11 STMicroelectronics STM Device in DFU Mode
将STM32设置为普通模式,将Artec插入BPI-M1+,得到以下日志:
root@OpenWrt:~# cat env.log ========= DEVNAME=bus/usb/001/006 ACTION=add SHLVL=1 HOME=/ SEQNUM=1009 BUSNUM=001 MAJOR=189 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MINOR=5 TYPE=2/2/0 DEVNUM=006 PRODUCT=20a0/4269/200 PWD=/ DEVTYPE=usb_device ---------- ========= ACTION=add SHLVL=1 HOME=/ SEQNUM=1010 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4/1-1.4:1.0 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MODALIAS=usb:v20A0p4269d0200dc02dsc02dp00ic02isc02ip01in00 TYPE=2/2/0 PRODUCT=20a0/4269/200 INTERFACE=2/2/1 PWD=/ DEVTYPE=usb_interface ---------- ========= ACTION=bind SHLVL=1 HOME=/ SEQNUM=1012 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4/1-1.4:1.0 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MODALIAS=usb:v20A0p4269d0200dc02dsc02dp00ic02isc02ip01in00 DRIVER=cdc_acm TYPE=2/2/0 PRODUCT=20a0/4269/200 INTERFACE=2/2/1 PWD=/ DEVTYPE=usb_interface ---------- ========= ACTION=add SHLVL=1 HOME=/ SEQNUM=1013 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4/1-1.4:1.1 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MODALIAS=usb:v20A0p4269d0200dc02dsc02dp00ic0Aisc00ip00in01 DRIVER=cdc_acm TYPE=2/2/0 PRODUCT=20a0/4269/200 INTERFACE=10/0/0 PWD=/ DEVTYPE=usb_interface ---------- ========= ACTION=bind SHLVL=1 HOME=/ SEQNUM=1014 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4/1-1.4:1.1 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MODALIAS=usb:v20A0p4269d0200dc02dsc02dp00ic0Aisc00ip00in01 DRIVER=cdc_acm TYPE=2/2/0 PRODUCT=20a0/4269/200 INTERFACE=10/0/0 PWD=/ DEVTYPE=usb_interface ---------- ========= DEVNAME=bus/usb/001/006 ACTION=bind SHLVL=1 HOME=/ SEQNUM=1015 BUSNUM=001 MAJOR=189 DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.4 TERM=linux SUBSYSTEM=usb PATH=/usr/sbin:/usr/bin:/sbin:/bin MINOR=5 DRIVER=usb TYPE=2/2/0 DEVNUM=006 PRODUCT=20a0/4269/200 PWD=/ DEVTYPE=usb_device ----------
可以看到,流程分别为
usb_device add
usb_interface add
usb_interface bind
usb_interface add
usb_interface bind
usb_device bind
想要区分出来,只用识别DRIVER是否为cdc_acm,且usb_interface为add
具体hotplug.json代码如下,在最下面加就行
[ "if", [ "and", [ "eq", "SUBSYSTEM", "usb" ], [ "eq", "ACTION", "add" ], [ "eq", "DEVTYPE", "usb_interface" ], [ "regex", "PRODUCT", "df11" ] ], [ "exec", "/root/QC/AutoRun", "STM32" ] ], [ "if", [ "and", [ "eq", "SUBSYSTEM", "usb" ], [ "eq", "ACTION", "add" ], [ "eq", "DEVTYPE", "usb_interface" ], [ "regex", "DRIVER", "cdc_acm" ] ], [ "exec", "/root/QC/AutoRun", "ESP32" ] ]
将/root/QC/AutoRun脚本改为如下,就能在/root/QC/env.log文件中看到是哪个芯片
root@OpenWrt:~/QC# cat AutoRun #!/bin/sh export HOTPLUG_TYPE="$1" echo $HOTPLUG_TYPE >> /root/QC/env.log
最后将AutoRun改为以下代码
#!/bin/sh export HOTPLUG_TYPE="$1" echo $HOTPLUG_TYPE >> /root/QC/env.log if [ "$HOTPLUG_TYPE" = ESP32 ] then /root/QC/AutoRun_ESP32 elif [ "$HOTPLUG_TYPE" = STM32 ] /root/QC/AutoRun_STM32 fi
在识别为STM32时运行/root/QC/AutoRun_STM32,在识别为ESP32 时运行/root/QC/AutoRun_ESP32
自动烧录
STM32的dfu固件烧写工具为dfu-util
下面是Tim老师给出的命令
dfu-util -a 0 -R -p 2-1.4.3 -D studuinobit_STM32F042_Flash_20190306.dfu
下面是dfu-util的具体使用方法:
root@OpenWrt:~# dfu-util -h Usage: dfu-util [options] ... -h --help Print this help message -V --version Print the version number -v --verbose Print verbose debug statements -l --list List currently attached DFU capable devices -e --detach Detach currently attached DFU capable devices -E --detach-delay seconds Time to wait before reopening a device after detach -d --device <vendor>:<product>[,<vendor_dfu>:<product_dfu>] Specify Vendor/Product ID(s) of DFU device -p --path <bus-port. ... .port> Specify path to DFU device -c --cfg <config_nr> Specify the Configuration of DFU device -i --intf <intf_nr> Specify the DFU Interface number -S --serial <serial_string>[,<serial_string_dfu>] Specify Serial String of DFU device -a --alt <alt> Specify the Altsetting of the DFU Interface by name or by number -t --transfer-size <size> Specify the number of bytes per USB Transfer -U --upload <file> Read firmware from device into <file> -Z --upload-size <bytes> Specify the expected upload size in bytes -D --download <file> Write firmware from <file> into device -R --reset Issue USB Reset signalling once we're finished -s --dfuse-address <address> ST DfuSe mode, specify target address for raw file download or upload. Not applicable for DfuSe file (.dfu) downloads
可见,只用将port识别出来就行,找了一会,发现在 DEVPATH变量中有:
DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.1/1-1.1:1.0
1-1.1就是我们要提取出来的数字,其中1-1是bus-port,代表1号bus的1号port,后面的.1代表它接的hub的1号口接了一个设备(我在M1+的板子上接了一个hub),我们只需在STM32识别到了之后将port提取出来就行
本来想用正则,而且式子也列出来了(另外强烈推荐球猫给的网站https://regex101.com/)
但是奈何技术不太过关,没找到正则在shell中的使用方法,于是使用了最土的办法,截取:和/两个符号中间的字符,分两步删掉
root@OpenWrt:~# DEVPATH=/devices/platform/soc@01c00000/1c14000.usb/usb1/1-1/1-1.1/1-1.1:1.0 root@OpenWrt:~# b=${DEVPATH##*/} && echo $b 1-1.1:1.0 root@OpenWrt:~# USBBUS=${b%:*} && echo $USBBUS 1-1.1
使用以上方法就能将port识别出来
最后直接替代就好了
dfu-util -a 0 -R -p $USBBUS -D studuinobit_STM32F042_Flash_20190306.dfu
ESP32烧录
ESP32部分就比较简单了,插上之后时ttyACM*,直接在hotplug.json加上以下代码就行
[ "if", [ "and", [ "eq", "SUBSYSTEM", [ "net", "input", "usb", "ieee1394", "block", "atm", "zaptel", "tty", "button" ] ], [ "regex", "DEVNAME", [ "^ttyACM" ] ], [ "eq", "ACTION", "add" ] ], [ "exec", "/root/QC/AutoRun", "ESP32" ] ]
在最后面加了个变量,用来标记ESP32或者STM32,/root/QC/AutoRun脚本中加个判断就能直接用了,$DEVNAME变量就是端口号
参考链接
正则表达式:https://www.runoob.com/regexp/regexp-syntax.html
Shell字符串截取(非常详细):http://c.biancheng.net/view/1120.html
regex101:https://regex101.com/
月球猫以及Tim老师
暂无评论