STM32MP157驱动开发——Linux CAN驱动
- 一、简介
- 1.电气属性
- 2.CAN协议
- 3.CAN速率
- 4.CAN FD 简介
- 二、驱动开发
- 1.修改设备树
- 2.FDCAN1控制器节点
- 3.修复 m_can_platform.c
- 4.使能 CAN 总线
- 5.使能FDCAN外设驱动
- 三、运行测试
- 1.移植 iproute2 和 can-utils 工具
- 2.测试
- 1)收发测试:
- 2)CAN FD协议测试
- 3. CAN 500K 收发异常处理方法
参考文章:【正点原子】I.MX6U嵌入式Linux驱动开发——Linux CAN驱动
一、简介
CAN 是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域,尤其是汽车领域,汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。上学的时候导师也说过,一个优秀的嵌入式工程师一定是一个优秀的 CAN 总线使用者。所以关于 CAN 总线的设计和驱动开发比较重要。本节就来学习一下开发板上的 CAN 接口驱动开发。
CAN 的全称为 Controller Area Network,也就是控制局域网络,以汽车电子为例,汽车上有空调、车门、发动机、大量传感器等,这些部件都是通过 CAN 总线连在一起形成一个网络。
在同一个 CAN 网络中所有单元的通信速度必须一致,不同的网络之间通信速度可以不同。CAN 的特点主要有以下几点:
- 1.多主控制
在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符 (Identifier 以下称为 ID) 决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜 (被判定为优先级最高) 的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。- 2.系统的柔软性
与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。- 3.通信速度快,距离远
最高 1Mbps (距离小于 40M),最远可达 10KM (速率低于 5Kbps),最新的 CAN FD 速度可以到 5Mbps。- 4.具有错误检测、错误通知和错误恢复功能
所有单元都可以检测错误 (错误检测功能),检测出错误的单元会立即同时通知其他所有单元 (错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止 (错误恢复功能)。- 5.故障封闭功能
CAN 可以判断出错误的类型是总线上暂时的数据错误 (如外部噪声等) 还是持续的数据错误 (如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。- 6.连接节点多
CAN 总线可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。
1.电气属性
CAN 总线使用两根线来连接各个单元:CAN_H 和 CAN_L,CAN 控制器通过判断这两根线上的电位差来得到总线电平,CAN 总线电平分为显性电平和隐性电平两种。显性电平表示逻辑“0”,此时 CAN_H 电平比 CAN_L 高,分别为 3.5V 和 1.5V,电位差为 2V。隐形电平表示逻辑“1”,此时 CAN_H 和 CAN_L 电压都为 2.5V 左右,电位差为 0V。CAN 总线就通过显性和隐形电平的变化来将具体的数据发送出去。
总线空闲时,就一直处于隐形。并且CAN 总线两端要各接一个 120Ω 的端接电阻,用于匹配总线阻抗,吸收信号反射及回拨,提高数据通信的抗干扰能力以及可靠性。
2.CAN协议
CAN 协议提供了 5 种帧格式来传输数据,其中数据帧和遥控帧有标准格式和扩展格式两种,标准格式有 11 位标识符(ID),扩展格式有 29 个标识符(ID)。
各种数据帧的组成字段可参考原子哥教程中的描述。
3.CAN速率
CAN2.0 最高速度为 1Mbps / 秒。对于 CAN 总线,一个位分为 4 段:
① 同步段(SS)
② 传播时间段(PTS)
③ 相位缓冲段 1(PBS1)
④ 相位缓冲段 2(PBS2)
4.CAN FD 简介
CAN FD 采用两种速率,控制段和仲裁段等使用标准的 CAN 速率,但是数据段会切换到更高的通信速率,比如 5Mbps。CAN FD 也对数据长度做了扩展,最大支持 64 字节。
改进:
1.增加一些控制位
EDL:用于指示当前为 CAN 帧还是 CAN FD 帧,标准 CAN 中此位为显性,在 CAN FD 中此位为隐性。
BRS:速率转换开关,为隐性的时候转换为可变速率,此时速率可变,BRS 到 CRC 之间使用可变速率。为显性的时候速率不变。
ESI:错误状态指示位,隐性的时候表示节点处于被动错误状态,显性的时候表示节点处于主动错误状态。
2.优化 CRC 算法
传统的 CAN 协议中,使用位填充的方式来保持同步,但是这种方法会对 CRC 造成干扰,导致错帧漏检。CAN FD 为此对 CRC 算法进行了优化,将填充位加入到差错校验码中进行计算,也就是以填充位的位流进行计算。
二、驱动开发
原理图:
CAN1_TX 和 CAN1_RX 是 STM3MP1 FDCAN 的发送和接收引脚,对应 STM32MP1 的 PH13 和 PI9 两个引脚。正点原子 STM32MP1 开发板上的 CAN FD 收发芯片有三种:MCP2562FDT、TJA1042T/3 或者 SIT1042T/3,这三种芯片 Pin to Pin 兼容,使用起来没有区别。SIT1042T/3为国产芯片,这里就以此为例进行开发。
R36 是一个 120 欧的端接匹配电阻。CAN_FD_STBY 是 SIT1042T/3 的高速与待机模式选择引脚,低电平为高速模式,连接在 PF12 引脚上,本节没有使用。
1.修改设备树
ST 原厂提供的设备树已经配置好了 FDCAN1 的节点信息,相关文档为 Documentation/devicetree/bindings/net/can/m_can.txt。在 stm32mp157-pinctrl.dtsi 文件中,存在 CAN 节点:
其引脚使用与开发板上的一致,所以不需要修改。
2.FDCAN1控制器节点
在 stm32mp153.dtsi 中,存在 m_can 节点:
根据 compatible 属性可以找到 STM32MP1 的 FD CAN 驱动源文件,为 drivers/net/can/m_can/m_can_platform.c。status 默认关闭。所以在自己的设备树中对其进行使能。在 stm32mp157d-atk.dts 中添加以下节点:
&m_can1 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&m_can1_pins_a>;
pinctrl-1 = <&m_can1_sleep_pins_a>;
status = "okay";
};
FDCAN1 两个状态的 pinctrl 节点分别为:m_can1_pins_a 和 m_can1_sleep_pins_a,并将 m_can1 节点的 status 属性改为“okay”,也就是使能 FDCAN1。
3.修复 m_can_platform.c
原子哥使用的教程中,ST官方对5.4.31版本的 CAN 驱动进行了维护,所以如果使用原子提供的内核源码,会出现不能进行收发数据的情况。可以从官方下载该版本的代码,或者使用原子哥提供的5.4.19版本驱动进行替换。即替换 m_can_platform.c 文件,位于源码目录下的 drivers/net/can/m_can/m_can_platform.c。
4.使能 CAN 总线
首先打开 CAN 总线子系统,在 Linux 下 CAN 总线是作为网络子系统的,在menuconfig中选中相应配置:
5.使能FDCAN外设驱动
三、运行测试
编译出新的内核镜像和设备树,然后启动开发板。
Linux 系统中把 CAN 总线接口设备作为网络设备进行统一管理,所有使用ifconfig -a
命令查看所有网卡。
1.移植 iproute2 和 can-utils 工具
iproute2 是 Linux 上有关 TCP/IP 网络的一系列工具。需要此工具进行配置 CAN 网络
设备。
在 buildroot 的 menuconfig 中进行使能:
can0 网卡的收发测试需要使用 can-utils 工具,在buildroot中路径如下:
然后使用sudo make
编译出新的根文件系统即可。
2.测试
由于手头没有相应的转接线,所以就贴上相关命令和原子哥的图。
1)收发测试:
设置 CAN 接口速率:
ip link set can0 type can bitrate 1000000
设置 can0 速度为 1000Kbit / 秒,两个 CAN 设备的速度要设置为相同速率。
打开 can0 网卡:
ifconfig can0 up
接收数据命令:
candump can0
在上位机使用 USB 转 CAN 设备,然后就可以通过串口助手发送信息。
开发板发送信息:
cansend can0 5A1#11.22.33.44.55.66.77.88
cansend 命令用于发送 can 数据,“5A1”是帧 ID,“#”号后面的“11.22.33.44.55.66.77.88”就是要发送的数据,十六进制。CAN2.0 一次最多发送 8 个字节的数据,8 个字节的数据之间用“.”隔开。
关闭 can0:
ifconfig can0 down
2)CAN FD协议测试
CAN FD 的波特率最高为 1MBit/s,数据波特率为 5 MBit/s。
ip link set can0 up type can bitrate 1000000 dbitrate 5000000 fd on
ip link set can0 up type can bitrate 200000 dbitrate 1000000 fd on
ip link set can0 up type can bitrate 100000 dbitrate 500000 fd on
这是三种不同的速率设置,可以根据实际情况进行修改。
然后使用以下命令打开开发板的接收功能:
candump can0
从上位机发送数据,就可以在开发板接收到信息。
从开发板发送数据:
cansend can0 123##300.11.22.33.44.55.66.77.88.99.aa.bb.cc.dd.ee.ff.00.11.22.33.44.55.66.77.88.99.aa.bb.cc.dd.ee.ff.00.11.22.33.44.55.66.77.88.99.aa.bb.cc.dd.ee.ff.00.11.22.33.44.55.66.77.88.99.aa.bb.cc.dd.ee.ff
CAN FD 一次最多能收发 64 个字节的数据。
3. CAN 500K 收发异常处理方法
使用标准 CAN 进行收发测试时,可能会出现使用 500K 波特率时开发板接收有问题,这个问题需要修改 TF-A 下的 PLL4 频率。打开 TF-A 源码中的 fdts/stm32mp157d-atk.dtsi 文件:
修改cfg设置,配置方法可以参考 docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt。
默认配置下 PLL4R=74.25MHz,修改后为 60MHz,也就是将 FDCAN 的时钟源设置为 60MHz。重新编译 TF-A,然后启动开发板即可。