基于MCP2515的Linux CAN总线驱动程序设计(三)

本文详细介绍了基于MCP2515的Linux CAN总线驱动程序的字符设备部分,包括设备结构体、中断函数、中断下半部处理、报文发送和接收的实现。通过硬件连接、驱动加载和测试程序展示了完整的驱动设计流程。
摘要由CSDN通过智能技术生成

1. 前言

        上篇文章介绍了使用SPI子系统设计的基于MCP2515的Linux CAN总线驱动程序,这篇文章主要介绍MCP2515的字符设备驱动功能函数的实现。

2. 硬件设计

        MCP2515与S3C2416的硬件连接图如图3所示。如硬件原理图可知MCP2515芯片连接在S3C2416芯片的SPI0上,中断接在GPF1上;MCP2515输出连接SN65HVD230 CAN总线收发器,SN65HVD230是德州仪器公司生产的3.3V CAN收发器。为了节省功耗,缩小电路体积,MCP2515 CAN总线控制器的逻辑电平采用LVTTL,SN65HVD230就是与其配套的收发器。


图1 MCP2515硬件连接图
 

3. MCP2515功能函数的实现


3.1 MCP2515设备结构体

        首先需要定义MCP2515的设备结构体,包含MCP2515驱动所需要的相关属性。

struct mcp2515_chip {
    canid_t own_id;                  // CAN ID
    canid_t broadcast_id;            // Broadcase ID
    CanBandRate bandrate;            // 波特率

    struct cdev cdev;                 // 字符设备结构体
    struct spi_device *spi;          // SPI 设备结构体
    struct class *class;             // Class类

    struct work_struct irq_work;    // 工作队列

    uint32_t count;                 // CAN 设备计数

    uint8_t *spi_transfer_buf;      // SPI传输缓冲区

      /* SPI输入输出缓冲区 */
    struct can_frame spi_tx_buf[MCP2515_BUF_LEN];
    struct can_frame spi_rx_buf[MCP2515_BUF_LEN];

    uint32_t rxbin;                 // 接收报文计数
    uint32_t rxbout;                // 读报文计数
    uint32_t txbin;                 // 发送报文计数
    uint32_t txbout;                // 发送报文计数

    wait_queue_head_t rwq;          // 读报文等待队列头
};

        在整个驱动中我们都需要使用这个设备结构体,所以在驱动注册成功后在probe函数中要创建这个设备结构体,并且对这个结构体相应的初始化。

static int __devinit mcp2515_probe(struct spi_device *spi)
{
    struct mcp2515_chip *chip;
    int ret;
    /* 为设备结构体申请空间 */
    chip = kmalloc(sizeof(struct mcp2515_chip), GFP_KERNEL);
    if (!chip) {
        ret = -ENOMEM;
        goto error_alloc;
    }
    
      /* 初始化设备结构体 */
    dev_set_drvdata(&spi->dev, chip);
    ……
    /* 初始化工作队列 */
    INIT_WORK(&chip->irq_work, mcp2515_irq_handler);
      /* 申请中断 */
    ret = request_irq(IRQ_EINT(1), mcp2515_irq, 
                      IRQF_DISABLED | IRQF_TRIGGER_FALLING, DEVICE_NAME, spi);
    if (ret < 0) {
        printk("MCP2515: Request_irq() Error!\n");
        goto error_irq;
    }
      /* 初始化等待队列头 */
    init_waitqueue_head(&chip->rwq);
    /* 注册设备 */
  	……
   printk ("MCP2515: MCP2515 Can Device Driver.\n");
}

        使用dev_set_drvdata函数把spi与设备结构体chip关联起来,在只有spi参数传入的情况下,可以使用dev_get_drvdata获取设备结构体chip。

 3.2 MCP2515中断函数

        根据芯片手册可知,MCP2515有8个中断源,当中断发生时,INT引脚将被MCP2515拉低为低电平,并且保持低电平状态直至MCU清除中断。

        由原理图可知MCP2515芯片外部中断接到S3C2416的外部中断1口上,所以在probe时使用request_irq申请外部中断1的中断。我们可以通过判断中断标志位的方式来接收数据。然而我们使用req

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值