这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【EEPW-Let'sdesign】MicrochipSAMA7D65-V/7E

共1条 1/1 1 跳转至页

【EEPW-Let'sdesign】MicrochipSAMA7D65-V/7EW-10|CAN-FD:QEMU里没有MCAN模型,手搓一个

菜鸟
2026-11-11 23:07:29     打赏

这颗芯片有 5 路 CAN-FD。但 QEMU 8.2 里没有任何 M_CAN 模型——只有 SJA1000、CTU CAN-FD、Xilinx CAN 这几种,都不是 Bosch 的 M_CAN。

所以这部分是完整的自研实现。

消息 RAM 是核心

M_CAN 和普通 CAN 控制器不一样,它的收发缓冲区不在寄存器里,而在一块独立的内存里。

设备树里给了两块地址:

reg = <0xe0828000 0x200>, <0x100000 0x7800>;
reg-names = "m_can", "message_ram";

第一块是寄存器,第二块就是消息 RAM,0x7800 字节。驱动直接 ioremap 过去,往里面读写帧。

模型里给这块内存单独建了一个 MemoryRegion,CPU 和内部逻辑共用同一块 buffer。

10_01_消息RAM.png【10_01_消息RAM】

一个省事的发现

本来以为要按 RXESC / TXESC 寄存器算出每个元素的尺寸,再算偏移。翻驱动代码发现不用:

#define RXF0_ELEMENT_SIZE   72
#define TXB_ELEMENT_SIZE    72
#define TXE_ELEMENT_SIZE    8

驱动里是硬编码的 72 字节。 不管配的是什么数据长度,元素都按 72 字节排。

72 正好是 8 字节头 + 64 字节数据,对应 CAN-FD 的满载荷。

这一下省掉一大块解析逻辑——模型只要按 72 字节搬运就行。

回环:把 TX 的帧搬进 RX

第一个目标是让帧能发出去、能收回来。M_CAN 自带 loopback 模式,TEST 寄存器的 bit 4。

流程:

写 TXBAR 触发发送
  → 从 TXB 取第 i 个元素(72 字节)
  → 复制到 RX FIFO0 的 put 位置
  → 更新 FFL / FGI / FPI
  → 拉 RF0N 中断

驱动那边收到中断后,读 RXF0S 拿到填充数和 get 索引,从消息 RAM 读出元素,再写 RXF0A 确认,硬件把读指针往前推一格。

RXF0S 的字段位置是:填充数 [6:0]、get 索引 [13:8]、put 索引 [21:16]。

测试

先把工具准备好。core-image-minimal 只有 busybox,它的 ip 不支持 type can,得单独编 iproute2 和 can-utils 塞进去。

配接口:

~ # ip link set can0 type can bitrate 500000 loopback on
~ # ip link set can0 up
~ # ip -details link show can0
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 …
     can <LOOPBACK> state ERROR-ACTIVE (berr-counter tx 0 rx 0)
     bitrate 500000 sample-point 0.875
     clock 40000000 parentdev e0828000.can

位时序被驱动接受了,链路起来了。

然后发帧:

10_02_CAN回环.png【10_02_CAN回环】

~ # candump can0 &
~ # cansend can0 123#11223344
  can0  123   [4]  11 22 33 44

~ # cansend can0 12345678#AABBCC
  can0  12345678   [3]  AA BB CC

~ # cansend can0 7FF#DEADBEEF
  can0       7FF   [4]  DE AD BE EF

标准帧、扩展帧、边界 ID,全部原样回来。

FD 帧发不出去

试 FD 长帧,cansend 直接拒绝:

CAN interface is not CAN FD capable - sorry.

看 ip -details 的输出,mtu 16——这是经典 CAN 的 MTU,FD 应该是 72。

驱动其实支持 FD,ctrlmode_supported 里一直有 CAN_CTRLMODE_FD,只是必须显式打开:

~ # ip link set can0 down
~ # ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on loopback on
~ # ip link set can0 up

加了 fd on 和 dbitrate,MTU 变成 72,再发:

~ # cansend can0 456##3112233445566778899AABBCCDDEEFF
  can0  456  [16]  11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00

~ # cansend can0 789##30011…EEFF      # 64 字节满载荷
  can0  789  [64]  00 11 22 33 … EE FF

16 字节和 64 字节都通了。

边界

这个模型验证的是驱动路径和数据通路:消息 RAM 布局对了、元素搬运对了、中断和 FIFO 指针握手对了。

没做的是对外通信——要真正挂到 CAN 总线上,得把模型接到 QEMU 的 CAN bus 上,再桥到宿主机的 SocketCAN。那是另一层的事,跟模型正确性无关。





关键词: Microchip     SAMA7D65-V     CAN         

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]