PCIe to CAN Linux 驱动详细说明

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_46621272/article/details/118248223?
采用 FPGA + SJA1000 实现 PCIe to CAN

Linux 驱动

  1. 定制支持 CAN 的内核。进 linux kernel 源代码文件夹。cd /opensource/kernel/linux-3.18.20/
    make menuconfig。见下图
    PCIe to CAN Linux 驱动详细说明_第1张图片
    PCIe to CAN Linux 驱动详细说明_第2张图片
    PCIe to CAN Linux 驱动详细说明_第3张图片
    PCIe to CAN Linux 驱动详细说明_第4张图片
    PCIe to CAN Linux 驱动详细说明_第5张图片

  2. 编译内核。make uImage

  3. 编写oem_pcie.c 驱动,该驱动是在 /linux-3.18.20/drivers/net/can/sja1000/ems_pci.c 基础上修改的,就是因为 ems_pci.c 文件最小,最容易修改。改完后只有不到8K 连注释不到300行比源文件还小。其实移植有几个知识点掌握就很好办,我将这几个知识点例出来。

		//★ oem_pci_tbl 设备表,这里的 0x10ee, 0x7011 在 FPGA 工程中有介绍
		static const struct pci_device_id oem_pci_tbl[] = {
			{0x10ee, 0x7011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
			{0,}
		};
		MODULE_DEVICE_TABLE(pci, oem_pci_tbl);
		
		//★ SJA1000 寄存器读函数
		static u8 oem_pci_read_reg(const struct sja1000_priv *priv, int reg)
		{
			return readb(priv->reg_base + reg);
		}
		
		//★ SJA1000 寄存器写函数
		static void oem_pci_write_reg(const struct sja1000_priv *priv,
						 int reg, u8 val)
		{
			writeb(val, priv->reg_base + reg);
		}
		
		//★ 允许中断函数
		static void oem_pci_enable_irq(struct oem_pci_card *card)
		{
			writel(1,card->conf_addr + 0x2004);						//XILINX XDMA 中的文档有描述
		}
		
		//★ 禁止中断函数
		static void oem_pci_disable_irq(struct oem_pci_card *card)
		{
			writel(0,card->conf_addr + 0x2004);						//XILINX XDMA 中的文档有描述
		}

		//★ SJA1000 原理图中采用的是 16MHz时钟,Linux 驱动初始化时钟的值需要除 2
		// 在调试时这个值整的不对,波特率总是差一半,查了很久
		//网上有个文章说 SJA1000 内部时钟是晶体的二分频。
		#define OEM_PCIE_CAN_CLOCK (16000000/2)	// SJA1000原理图 16MHz,这里要除 2
		
		//★ 与FPGA XDMA IP 相关的一些常量的定义
		#define OEM_PCIE_CONF_BAR	1		// XILINX FPGA PCIE CONFIG REG BAR
		#define OEM_PCIE_CONF_SIZE	65536	// 在FPGA PCIE设计中 XDMA 寄存器空间 64K
		#define OEM_PCIE_BASE_BAR	0		// XILINX FPGA AXI Lite Master Interface BAR
		#define OEM_PCIE_BASE_SIZE	1024*1024 	// FPGA_PCIE 分配的空间 1M,
					// FPGA XDMA 中分配的地址"PCIe to AXI Lite Master Interface"
		
		#define OEM_PCIE_CAN_BASE_OFFSET	0x20000 // 在 FPGA PCIE 设计中 
													// AXI_EPC 的地址与该值对应 
		#define OEM_PCIE_CAN_CTRL_SIZE  	4096	// 在 FPGA PCIE 设计中 
													// AXI_EPC 的地址大小
		
		//★ oem_pci_post_irq   函数可以不要,空返回就可以。
		//★ oem_pci_card_reset 函数可以不要,空返回就可以。
  1. 在调试时,运行 can-utils-master 工具测试出现戳我“Create socket failed: Address family not supported by protocol” 错误,折腾很久,是当前内核不支持 CAN 。linux 内核需要重新定制,需要支持 CAN 。按上面的图去重新编译内核就行。

  2. 编译驱动

  3. 用新编译好的内核启动设备,加载 insmod oem_pcie.ko

  4. 用 can-utils-master 测试 CAN 通讯。

  5. 有技术问题可以联系 [email protected]

连接:采用 FPGA 实现 <PCIe to CAN> 网卡的设计 https://blog.csdn.net/qq_46621272/article/details/118242161?

你可能感兴趣的:(FPGA+嵌入式,linux,fpga,pcie,sja1000,can)