一、CAN的相关资料
1.《7A2000用户手册》
2.《CAN总线协议中文版》
3.《SJA1000中文版》
初次接触CAN,调试之前建议仔细阅读以上文档。
二、搭建硬件环境
以3A5000+7A2000开发板为例,7A2000的CAN引脚与UART复用,因此两者不可以同时存在,调试CAN时需要硬件工程师确认已经将UART相关引脚断开,将CAN相关引脚接入控制器,如下图所示,如果调试CAN0,CAN2需要将R3671、R3673、R3674、R3676的电阻接上,将电阻R3583、R3585、R3586、R3588去掉。
以测试CAN0与CAN2两个控制器互相收发数据为例,需要使用杜邦线将两个控制器的H接到一起,L接到一起如下图所示。
三、软件环境
首先需要支持7A2000的PMON。
3.1在ACPI表中添加CAN的传参
以CAN0为例,需要修改Targets/ls3a5000_7a/acpi_tables/platform.asl文件,增加如下代码
+ Device (CAN0)
+ {
+ Name (_HID, "LOON0009") // _HID: Hardware ID //制定的设备ID用来匹配内核驱动
+ Name (_UID, 0x0) // _UID: Unique ID//设备号
+ Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings//资源
+ {
+ QWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x0000000000000000, // Granularity
+ 0x0000000010080400, // Range Minimum //控制器起始地址
+ 0x00000000100804FF, // Range Maximum//结束地址
+ 0x0000000000000000, // Translation Offset
+ 0x0000000000000100, // Length//长度
+ ,, , AddressRangeMemory, TypeStatic)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
+ {
+ 75,//指定中断号
+ }
+ })
+ Name (_DSD, Package (0x02) // _DSD: Device-Specific Data
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device Properties for _DSD */,
+ Package (0x01)
+ {
+ Package (0x02)
+ {
+ "clock", //设备自定义的数据
+ 50000000
+ }
+ }
+ })
+
+ }
详细内容见0001-add-can-support.patch// 增加CAN的ACPI传参
3.2增加PMON下CAN测试命令
详细内容见0001-add-pmon-can-test-cmd.patch。
需要说明的是此测试文件是以CAN0和CAN2互相收发数据测试为前提,如果测试其他控制器需要修改里面的控制器基地址。
简单的测试说明如下:
1.can
测试程序会分别进行15K、100K、200K、250K、500K、625K、1000K波特率下的CAN0和CAN2标准帧收发测试.,测试通过则每个波特率下均打印PASS
2.can100_s、can200_s、can250_s、can500_s、can1000_s
控制CAN0发对应波特率下的标准帧,
3.can100_r、can200_r、can250_r、can500_r、can1000_r
控制CAN0收对应波特率下的标准帧
4.can_sel ,can_rx
扩展模式下自测试
5.can_ext
测试程序会分别进行15K、100K、200K、250K、500K、625K、1000K波特率下的CAN0和CAN2扩展帧收发测试.,测试通过则每个波特率下均打印PASS
6.can_en
将引脚复用成CAN功能
3.3 配置引脚复用成CAN功能
相关寄存器说明见7A2000手册 4.7章节引脚复用配置寄存器1。
实际操作只需要在PMON命令行下输入can_en命令。
3.4 配置内核CAN驱动
增加CAN ACPI传参解析代码
补丁0001-add-7a2000-can-support.patch
最新的4.19.190内核已经集成了这个补丁,如果使用的是2022年3月份以前的内核需要打上上面的补丁。
3.5 安装系统下的linux测试软件
3.5.1下载canutils,libsocketcan。
libsocketcan地址: https://public.pengutronix.de/software/libsocketcan/libsocketcan-0.0.11.tar.bz2 #0.0.11版本
canutils地址: https://public.pengutronix.de/software/socket-can/canutils/v4.0/canutils-4.0.6.tar.bz2 #4.0.6版本
3.5.2 编译
编译libsocketcan:
tar -jxvf libsocketcan-0.0.11.tar.bz2 -C /home
cd /home/libsocketcan-0.0.11
mkdir out
cp /usr/share/libtool/build-aux/config.sub config/autoconf/config.sub
./configure --host=loongarch64-linux-gnu --prefix=/home/libsocketcan-0.0.11/out --build=loongarch64-linux-gnu
make
make install
配置环境变量
export LD_LIBRARY_PATH=/home/libsocketcan-0.0.11/out/lib/:$LD_LIBRARY_PATH
编译canutils:
tar -jxvf canutils-4.0.6.tar.bz2 -C /home
cd /home/canutils-4.0.6
mkdir out
cp /usr/share/libtool/build-aux/config.sub config/autoconf/config.sub
将 libsocketcan 里面include文件夹下的头文件 libsocketcan.h can_netlink.h 复制到 canutils 的 include 里。
./configure --host=loongarch64-linux-gnu --build=loongarch64-linux-gnu --prefix=/home/canutils-4.0.6/out libsocketcan_LIBS=-lsocketcan LDFLAGS=“-L/home/libsocketcan-0.0.11/out/lib/” libsocketcan_CFLAGS=“-I/home/libsocketcan-0.0.11/out/include”
make
mkae install
配置环境变量
export PATH=/home/canutils-4.0.6/out/bin/:/home/canutils-4.0.6/out/sbin/:$PATH
3.6 linux系统下测试
ifconfig can0 down
ip link set can0 type can bitrate 125000 loopback off //配置can频率125khz
ip link set can0 up
candump can0//等待接收数据
ifconfig can1 down
ip link set can1 type can bitrate 125000 loopback off //配置can频率125khz
ip link set can1 up
cansend can1 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88//发送数据
3.7 如何计算波特率
3.7.1背景知识
由于CAN通信中的信号是二进制的,所以对CAN来说,波特率等于比特率。
即波特率等于一秒传输的bit数。
一个bit timing 如下图所示:
基本上,CAN位周期可以细分为四个时间段。每个时间段由若干个时间量程(time Quanta, tq)组成。时间量程是所有配置值的最小时间单位。
SYNC_SEG:是1个时间量程长度。它用于同步各个总线节点。
pro_seg:可编程为1,2,…8时间量程长。它被用来补偿网络上的信号延迟。
PHASE_SEG1:可编程为1,2,…8时间量程长。该算法用于补偿边缘相位误差,在重同步过程中可能会被延长。
PHASE_SEG2 :(Seg 2)是PHASE_SEG1和信息处理时间的最大值。它还可用于补偿边缘相位误差,在重同步过程中可以缩短时间。对于这一点,PHASE_SEG2的最小值是SJW的值。
信息处理时间小于或等于2个时间量程。
时间量程的总数必须从8到25。(较新的CAN控制器可能允许其他范围。检查如博世M_CAN。
SJW:计算出的波特率是个理论值,在实际的网络通信中由于存在传输的延时、不同节点的晶体的误差等因素,使得网络CAN的波特率的计算变得复杂起来。CAN在技术上便引入了重同步的概念,以更好的解决这些问题。这样重同步带来的结果就是要么时间段1(Tseg1)增加TSJW(同步跳转宽度SJW+1),要么时间段减少TSJW,因此CAN的波特率实际上有一个范围:1/(Tbit+Tsjw) ≤CANbps≤1/(Tbit-Tsjw)。
SAM:决定每比特时间采集的CAN总线采样数。
3.7.2 CAN波特率相关寄存器BRT0 BRT1。
7A2000手册多次提到SJA1000,因此猜测兼容SJA1000的寄存器解释。SJA1000只使用两个8位寄存器来设置CAN协议所需的位定时参数。一个寄存器BTR0包含位定时预分度器的值,另一个寄存器BTR1包含PHASE_SEG1和PHASE_SEG2的值。PHASE_SEG1是根据CAN规范(PROP_SEG + PHASE_SEG1)来编程的。
3.7.3计算波特率
内部时钟周期的频率是外部振荡器的一半,7A2000 CAN外部时钟频率50M,则内部时钟为25M。
波特率计算公式:
25M/(1+BRT0[0-5])/(1+(1+BRT1[6:4])+(1+BRT1[3-0])))
采样点计算公式:
(1+(1+TSEG1))/(1+(1+TSEG1)+(1+TSEG2))