龙芯3A5000+复旦微FPGA+Xilinx XDMA 驱动打造工业级多路CAN卡实录

框架图

其中FPGA CAN卡实现框图

开发环境

硬件平台

龙芯3A5000, 龙芯首款loongarch64架构平台

操作系统

国产麒麟V10系统

驱动移植

Xilinx 在github 有他们维护的dma开源仓库:https://github.com/Xilinx/dma_ip_drivers

Xilinx旨在免去用户从头开发dma 驱动的痛苦。

readme文档中明确表示支持的操作系统和内核版本有:

但我在实际项目中已经实践过了,移植到龙芯3A5000或者是FT/D2000 平台的国产化麒麟V10(内核版本5.14.x)操作系统下都是没有问题的。

驱动加载成功示意图:

xdma 节点生成:

项目中用到了xdma0_c2h_0/xdma0_h2c_0 以及12路中断 xdma0_events0 ~xdma0_events11。

寄存器读写示例:

API实现

部分寄存器定义示例

/*多路AutoCan 寄存器配置区-bar2 对应的地址空间*/

/*多路xilinx CAN 寄存器配置区-bar2 对应的地址空间*/

/*多路 CAN 数据 DMA 访问空间偏移*/

麒麟V10下API接口示例:

int can_init(uint8_t channel);

int can_set_bitrate(uint8_t channel, uint32_t bitrate, int sample_point);

int can_set_mode(uint8_t channel, int mode);

int mcan_open();

int mcan_close();

void mcan_interrupt_monitor_pthread_init();

int can_recv(uint8_t channel, can_frame *pframe, int *frame_cnt);

//单次发送的frame_cnt 最大不超过256帧

int can_send(uint8_t channel, const can_frame *pframe, int frame_cnt);

void can_enable_accept_filter(uint8_t channel, uint32_t filter_index);

uint32_t can_get_enable_accept_filter(uint8_t channel);

void can_disable_accept_filter(uint8_t channel, uint32_t filter_index);

int can_set_accept_filter(uint8_t channel, uint32_t filter_index, uint32_t mask, uint32_t id);

int can_get_rx_errcnt(uint8_t channel);

int can_get_tx_errcnt(uint8_t channel);

/*bit0 ~ bit11, 对应状态指示*/

uint32_t can_get_status(uint8_t channel);

/*bit 4: 1 ACK Error, bit3: 1 Bit Error, bit2: 1 Stuff Error, bit 1: 1 Form Error, bit 0: 1 CRC Error*/

int can_get_err_status(uint8_t channel);

基于QT的图形化CAN DEMO 实现

测试界面

测试界面如图1-1所示,不同显示器和分辨率条件下, 显示效果会有差异。

图1-1 测试界面

测试程序支持1到10路can 通道收发测试,如图1-2所示:

默认情况下第一次打开程序接收、发送按钮处于不可点击状态

默认情况下没有任何通道被选择, 所以测试之前必须在配置区选择对应的can通道,每次修改完配置都需要点击确认来使配置生效。点击确认后,当各个通道can参数配置完成, 确认按钮会变为深蓝色,当选择的通道越多,确认按钮变色的时间会延长,当10个通道都选择时,变色时间需要5秒, 请耐心等待一会, 确认按钮变色后, can可以进行接收或是发送了。

单通道接收数据、接收帧数会显示在右侧对应的接收区域。

单通道发送完成后, 发送帧数会显示在右侧对应的发送区域。

多通道接收、发送数据不在UI界面上显示, 而是以文件形式存储, 存储位置是测试程序所在目录。

接收文件的命名方式是canx_recv.log, 发送文件的命名方式是canx_snd.log,其中x代表通道号, 范围是1到10,canx_recv.log存储的是接收数据与最终接收到的can帧数,canx_snd.log只存储发送的帧数。

图1-2 测试区说明

单通道测试

单通道收

选择对应通道, 比如can2、配置通信速率比如1000k,然后点击确认, 点击接收后准备接收。

PC机端,相应的can测试程序配置好通道,通信速率, 发送信息后点击发送。

如图2-1所示,接收完成后,UI上会显示对应的帧计数与接收数据,接收帧数据如果大于10000行, 只保留最新的10000行数据。可以通过清空接收,清除帧计数与接收数据,接收过程可以点击停止接收来中断接收,如要重新接收需要再次点击接收。

图2-1单通道接收

单通道发

选择对应的can通道、通信速率、帧类型、帧格式,填充好帧ID、帧数据、选择每次发送单帧还是每次发送多帧、配置发送次数、发送间隔,点击确认,点击发送。

点击清空发送会清空帧计数,点击停止发送会中止发送过程。

图2-2单通道发

多通道测试

多通道收发测试与单通道收发测试不同的点是, 接收与发送数据不在UI界面上显示,而是以文本文件的形式存储,文件就存储在UI程序所在目录:

接收文件如图2-3所示,要查看文件之前,确保对端已发送完成,并点击停止接收按钮,如若没有点击停止接收,最后部分内容可能没有完全写入文件。

图2-3接收log文件

通过合适的文本编辑器比如vim, 打开接收log文件, 会看到如图2-4所示的接收内容。

图2-5 接收文件内容

多通道发送帧计数log文件如图2-6所示:

图2-6 发送帧计数log文件