框架图

其中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文件