WIFI+USBIP+MCU=无线USB设备

请注意,本文提供方法基于zephyr OS制作,由于目前zephyr项目的USB子系统处于大规模重构状态,所以本方案不受zephyr正式支持。详细请参考:

https://github.com/zephyrproject-rtos/zephyr/pull/46862

背景

目前,我们有许多MCU项目利用USB协议与PC进行通信,绝大多数使用USB从机协议,随着Wifi协议的广泛使用以及速度的提升,我认为绝大多数的USB设备都可以经由网络协议而渐渐变得无线化。

但是,如果完全将协议栈转换为网络,会导致一系列兼容软件或驱动需要再次适配,较大的开发量和不明显的收益使得各大厂商在这方面进展缓慢。

本文介绍一种基于USBIP的USB设备无线化方法,希望能够推进设备线束的无线化进程。

USB with WIFI

灵感来源(废话部分,技术无关,可以跳过😄)

前段时间有幸从artery公司木一川先生处得到一片at32 demo板,正巧促使我简单的学习了一下openocd和cmsisdap。发现cmsis-dap协议很容易就可以在zephyr中引用,以获得大量开发板支持。

但是如果只是制作一个普通的dap仿真器,比较缺少挑战性,因此我决定尝试制作无线的仿真器。

最初的目标是通过TCP转发cmsis-dap协议,修改openocd以支援网络设备,但是后面我意识到这会导致windows的KEIL和IAR等IDE环境难以运用。

因此,我将目标转向USB设备的网络访问,因此了解了USBIP协议,并且偶然发现zephyr OS中对USBIP是有部分实现的,我只需要简单的将他扩展到其他设备即可,因此便有了本文。

方案介绍

再次提示,本方案虽然基于zephyr OS制作,但是由于zephyr OS的USB subsystem处于大规模重构状态,所以不受zephyr主线支持!

实现代码请参考:https://github.com/zephyrproject-rtos/zephyr/pull/46862

实际在下面设备中运行通过:

传统USB程序结构

这里指的传统zephyr USB 设备程序(因为zephyr系统目前没有host设备,这也是大规模重构的原因)。

如果您的程序目前采用其他方式架构(可能大部分程序都是吧),您首先需要将其移植到zephyr OS。(目前USB subsystem处于不稳定状态,商业用户需要谨慎考虑)

zephyr OS USB DEVICE

USBIP 网络USB设备

本方案工作在UDD层,通过注册zephyr USB device驱动,并将其转换为USBIP协议。因此没有虽然没有USB硬件,但是在操作系统看来和有USB驱动是一样的。

示意图

注意:

  • 这不是标准USBIP Server的实现,但是我认为对于绝大多数的USB设备已经足够实现功能

使用

MCU程序

建议创建如下application

  • 启动后的wifi配置:帐号,密码,功耗等(有线网络可忽略)
  • 静态IP或DHCP服务

简单使用教程

  • 使用usbip客户端,确认基本通信
usbip list -r FEILONG-CMSIS-DAP
  • 挂载usbip设备
sudo usbip attach -r FEILONG-CMSIS-DAP -b 1-1
  • 调试可以使用wireshark,内置有USBIP协议。

windows

请参考

https://github.com/cezanne/usbip-win

有些功能可能需要使用zadig安装驱动:

https://zadig.akeo.ie/

linux

linux用户应该不需要多说,参考archlinux wiki即可使用。

https://wiki.archlinux.org/title/USB/IP

注意:

在linux上使用时,如果在使用过程中,没有detach直接复位、断电等,会造成linux内核出现异常,重启后即可解决。(windows没有发现此类问题)

参考链接

CAN232/CANUSB调查

最近研究了一下廉价CAN分析设备的原理,顺便明白了和CAN-OE设备的差距真的是天上地下.不过存在着不少优点还是可以学习的.下面是商品链接:

https://www.can232.com/

从名字上就可以看出这是一个串口到can数据包的转换工具,但是搜索很久都没找到通信协议,插在电脑上也不会主动发送消息,正在我百思不得其解的时候,发现了Linux内核里面有个叫做slcan的驱动模块,里面写着CAN232设备的网址.于是先调查下slcan是个什么东西.

slcan

全名 serial line CAN interface driver ,正好是CAN232设备的支持模块,需要配合slcand来使用(位于can=utils程序中).

初始化slcan很简单,正常初始化即可,但是如果我们把CAN232换成普通串口进行抓包,也是可以初始化的o.o

因此在打开设备时候可以捕获到下面数据(结尾均为0x0d,即’\r’):

C
S6
F
O

根据slcand的代码,可以判断相应字母(区分大小写)的意思,每个命令0x0d结尾

C -> 关闭
S6 -> 速度500k (参考: https://elinux.org/Bringing_CAN_interface_up#SLCAN_based_Interfaces)
F ->  获取状态
O -> 打开设备
// 下面这些也是代码中描述的协议
L -> 只听模式
s -> 设置波特率

//数据报文(大写代表扩展帧,小写代表数据帧)
t 数据帧
r 远程帧

//回复结尾
0x0d 正常
            异常(我忘了o.o,回头再试一下)

z 发送成功

因此,随便一个串口只要按照上面格式发送数据就可以被linux转换为CAN消息.当然这样的协议存在明显的缺点,即抗干扰能力差(不过CAN232采用了FTDI的串口芯片,一般实验室情况下稳定性足够了).

最后补上一张串口助手模拟的CAN.

slcanfd

这个串口模块非常古老,因此不支持CAN-FD的协议,但是内核驱动写的很清晰易懂,配合虚拟串口回环和cangen工具,制作了一个支持CAN-FD的驱动https://github.com/feilongfl/slcanfd.

首先模块名字改成了slcanfd,编译安装并手动加载即可使用slcand进行启动.(注意卸载slcan模块,否则会冲突)

后续可以考虑修改下slcand工具,增加下数据速度设置.在stm32G431上配合usb cdc跟fdcan做个usbcanfd(淘宝好像也有现成的,不过我想玩玩画板子,4层板都快成白菜价了)

发送接收展示:

pc发送不加速canfd
pc发送加速canfd
pc发送普通CAN(兼容原格式)
串口发送(CANFD Only)
串口发送(CANFD+CAN)

顺便wakatime也挺好玩的,能看到调查这堆东西花了多少时间:

解决10min netdev budget ran outs警报

问题

在netdata监控中一直被报警10min netdev budget ran outs,查找softnet项。

原文

Statistics for CPUs SoftIRQs related to network receive work. Break down per CPU core can be found at CPU / softnet statistics. processed states the number of packets processed, dropped is the number packets dropped because the network device backlog was full (to fix them on Linux use sysctlto increase net.core.netdev_max_backlog), squeezed is the number of packets dropped because the network device budget ran out (to fix them on Linux use sysctl to increase net.core.netdev_budget and/or net.core.netdev_budget_usecs). More information about identifying and troubleshooting network driver related issues can be found at Red Hat Enterprise Linux Network Performance Tuning Guide.

机翻

与网络接收工作相关的CPU SoftIRQ的统计信息。 可以在CPU / softnet统计信息中找到每个CPU核心的细分。 处理状态处理的数据包数量,丢弃的数据包丢失是因为网络设备积压已满(要修复它们在Linux上使用sysctl增加net.core.netdev_max_backlog),挤压的是因为网络设备预算而丢弃的数据包数量 用完(在Linux上修复它们使用sysctl来增加net.core.netdev_budget和/或net.core.netdev_budget_usecs)。 有关识别和排除网络驱动程序相关问题的更多信息,请参阅“红帽企业Linux网络性能调整指南”。

解决方法

执行以下命令:

sysctl net.core.netdev_max_backlog
sysctl net.core.netdev_budget

提示

net.core.netdev_max_backlog = 1000
net.core.netdev_budget = 300

这两个默认值很小,由于本人不了解tcp底层原理,只能依照说明调大这两个值。

sudo sysctl net.core.netdev_max_backlog=10000
sudo sysctl net.core.netdev_budget=3000

同时,根据说明调整

sudo sysctl net.core.netdev_budget_usecs=20000

调整过后,softnet蓝线减小为零,十分钟左右后消失,警报也随之消失。

screenshot-2018-12-08-at-17-41-38-e1544262219996.png

如果是在路由器或其他低功耗设备中sysctl命令可能有busybox提供,设置时需要-w参数

但是,重启后会失效,将上述参数保存至/etc/sysctl.conf