64 linux spi设备驱动之mcp2515(can控制器)驱动

mcp2515是一个spi接口的can控制器, 也就是我们通过spi接口把数据交给mcp2515, 它再把spi数据转换成can数据发出.

这里写图片描述

MCP2515的接口:
  INT 中断线  --->   GPIOA(10) 
  SCK 时钟线  --->   SPI0_CLK
  SI         --->   SPI0_MOSI
  SO         --->   SPI0_MISO
  CS         --->   SPI0_CS0
  GND        --->   GND
  VCC        --->   3.3v

linux内核里已提供了mcp2515的设备驱动, 是一个spi设备驱动

make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

  [*] Networking support  --->
    <*>   CAN bus subsystem support  --->
        <*>   Raw CAN Protocol (raw access with CAN-ID filtering)
        CAN Device Drivers  ---> 
            <*>   Microchip MCP251x SPI CAN controllers // mcp2515设备驱动

驱动源码在”drivers/net/can/mcp251x.c “

static const struct spi_device_id mcp251x_id_table[] = {
    { "mcp2510",    CAN_MCP251X_MCP2510 },
    { "mcp2515",    CAN_MCP251X_MCP2515 },
    { },
};

static struct spi_driver mcp251x_can_driver = {
    .driver = {
        .name = DEVICE_NAME,
        .bus = &spi_bus_type,
        .owner = THIS_MODULE,
    },   

    .id_table = mcp251x_id_table, //按id_table里的内容匹配
    .probe = mcp251x_can_probe,
    ...
};
//还需要查看probe函数,确认spi设备需提供的资源
static int __devinit mcp251x_can_probe(struct spi_device *spi)
{
    struct net_device *net;
    struct mcp251x_priv *priv;
    struct mcp251x_platform_data *pdata = spi->dev.platform_data; //当我们描述spi_board_info设备信息时,需要提供struct mcp251x_platform_data类型的平台数据. 还需要提供中断号.
    int ret = -ENODEV;

    ...
}

struct mcp251x_platform_data {
    unsigned long oscillator_frequency; // MCP2515用的时钟频率(8MHz)
    unsigned long irq_flags;  //中断标志, 如不设,则设备驱动里使用下降沿触发方式
    int (*board_specific_setup)(struct spi_device *spi); //设备初始化所需的工作,如有实现,在设备驱动匹配时调用
    int (*transceiver_enable)(int enable); //当设备open/close时调用,可把设备工作前和结束工作前所需的操作写在函数里
    int (*power_enable) (int enable); //设备实现的功能函数,在设备驱动probe和remove时调用
};


在script.bin里描述的spi设备不可带platform_data, 描述mcp2515的设备时需要platform_data, 所以只能直接用spi_board_info来描述.

先把script.bin里描述的spi设备去掉, 因mcp2515用spi0_cs0, 一个片选线只能由一个设备使用
在内核里描述mcp2515设备的代码:

#include <linux/spi/spi.h>
#include <linux/can/platform/mcp251x.h>

/* spi device controller state, alloc */
struct sunxi_spi_config {
    int bits_per_word; //8bit
    int max_speed_hz;  //80MHz
    int mode; // pha,pol,LSB,etc..
};


struct mcp251x_platform_data mcp2515_pdata = {
    8000000, 0, NULL, NULL, NULL,
};

struct sunxi_spi_config sunxi_data =  {
    8, 2000000, SPI_MODE_0
};

struct spi_board_info spi_infos[] = {
    {
        .modalias = "mcp2515",
        .platform_data = &mcp2515_pdata,    
        .controller_data = &sunxi_data,//需查控制器的驱动代码,可得知需要提供struct sunxi_spi_config类型数据. 注意不同的同台,需要数据类型也会不同

//      .irq = gpio_to_irq(GPIOA(10)),
        .max_speed_hz = 2000000, //2MHz
        .bus_num = 0, // 接着编号为0的控制器
        .mode = SPI_MODE_0,
    },

};

static void __init sunxi_dev_init(void)
{

    spi_infos[0].irq = gpio_to_irq(GPIOA(10));
    spi_register_board_info(spi_infos, ARRAY_SIZE(spi_infos));
    ...
}


重编内核,使用新内核镜像启动后,”ifconfig -a”有can0设备节点出现即表示已驱动好

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值