Linux系统自带SPI接口驱动自测

本文介绍如何配置Linux内核以支持SPI接口,并通过spidev_test.c进行自回环测试。主要内容包括修改设备树和内核配置以启用spidev设备驱动,以及解释生成的设备节点号spidev32766.0的具体含义。


转自http://blog.youkuaiyun.com/yaolanshu_june/article/details/52152790

本文主要验证kernel\Documentation\spi目录下spidev_test.c的测试例程,能否正常控制SPI接口。

一、驱动配置
1.修改设备树
找到内核源码的linux-imx_share\arch\arm\boot\dts目录下的imx6qdl-sabresd.dtsi,找到ecspi1的代码

将spidev这段注释去掉,开启这段代码。

2.修改内核配置
输入:make ARCH=arm menuconfig进行内核配置,进入配置界面,依次选择Device Drivers->SPI support,使User mode SPI device driver support选项起作用,选择Y,并save。

选择这个的目的是使spidev.c参与编译,原因可以参考linux-imx_share\drivers\spi目录下的Kconfig和Makefile。


配置好之后,运行./build.sh,编译生成zImage,zImage-imx6dl-sabresd-emmc.dtb烧写进板子。
检查新烧进去的系统里,dev目录下有无spidev32766.0。如有,表示spidev的设备驱动烧写成功。



二、测试
1.找到ECSPI的引脚,连接MISO和MOSI,进行自回环测试。


2.编写makefile生成自测代码spidev_test.c对应的可执行程序。


 使用rz命令,将spidev_test上载至板子

接收的数据正确,自回环测试成功。
------------------------------------------------------------------------------------------------------------------------------------
疑问:生成的设备节点为什么是spidev32766.0?

在spidev.c中的函数spidev_probe里,找到设备节点的赋值。
[objc] view plain copy print?
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);  //计算出设备号 
//创建设备/dev/spidev%d.%d(spidev总线号.片选号) 
dev = device_create(spidev_class, &spi->dev, spidev->devt, 
            spidev, "spidev%d.%d", 
            spi->master->bus_num, spi->chip_select); 
下面看下spi->master->bus_num和spi->chip_select的值。

在drivers/spi目录下的spi.c文件中,spi_alloc_master函数中,给master->bus_num = -1进行了初始化。
[objc] view plain copy print?
struct spi_master *spi_alloc_master(struct device *dev, unsigned size) 

    struct spi_master   *master; 
 
    if (!dev) 
        return NULL; 
 
    master = kzalloc(size + sizeof(*master), GFP_KERNEL); 
    if (!master) 
        return NULL; 
 
    device_initialize(&master->dev); 
    <span style="color:#3333ff;">master->bus_num = -1;  //初始化 
    <span style="color:#3333ff;">master->num_chipselect = 1; 
    master->dev.class = &spi_master_class; 
    master->dev.parent = get_device(dev); 
    spi_master_set_devdata(master, &master[1]); 
 
    return master; 

在spi_register_master函数中,对bus_num进行了处理
[objc] view plain copy print?
/* convention:  dynamically assigned bus IDs count down from the max */ 
    if (master->bus_num < 0) <span style="font-family: Arial, Helvetica, sans-serif;">{</span> 
[objc] view plain copy print?
/* FIXME switch to an IDR based scheme, something like
 * I2C now uses, so we can't run out of "dynamic" IDs
 */ 
master->bus_num = atomic_dec_return(&dyn_bus_id); 
dynamic = 1; 

其中dyn_bus_id计算结果是32767
[objc] view plain copy print?
static atomic_t     dyn_bus_id = ATOMIC_INIT((1<<15) - 1); 
[objc] view plain copy print?
#define atomic_dec_return(v)    (atomic_sub_return(1, v)) 
[objc] view plain copy print?
static inline int atomic_sub_return(int i, atomic_t *v) 

    unsigned long flags; 
    int val; 
 
    raw_local_irq_save(flags); 
    val = v->counter; 
    v->counter = val -= i; 
    raw_local_irq_restore(flags); 
 
    return val; 

如此计算出master->bus_num=32766。
of_register_spi_devices函数里chip_select的获得是通过value赋值的,而value是通过设备树里的reg后面的值取得的
[objc] view plain copy print?
/* Device address */ 
        rc = of_property_read_u32(nc, "reg", &value); 
        if (rc) { 
            dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", 
                nc->full_name, rc); 
            spi_dev_put(spi); 
            continue; 
        } 
        spi->chip_select = value; 
[objc] view plain copy print?
spidev: spidev@0
        spi-max-frequency = <24000000>;   
        reg = <0>;   
        compatible = "rohm,dh2228fv";        
    }; 
所以生成的设备节点号是spidev32766.0。

如果在imx6qdl-sabresd.dtsi设备树里,改成下面这样,则生成的设备节点号是spidev32766.1。
[plain] view plain copy print?
&ecspi1 { 
    fsl,spi-num-chipselects = <2>; //改成2 
    cs-gpios = <&gpio2 30 0>; 
    pinctrl-names = "default"; 
    pinctrl-0 = <&pinctrl_ecspi1_1>; 
    status = "okay"; 
 
    flash: m25p32@0
        #address-cells = <1>; 
        #size-cells = <1>; 
        compatible = "winbond,w25q32"; 
        spi-max-frequency = <20000000>; 
        reg = <0>; 
    }; 
 
    spidev: spidev@1
        spi-max-frequency = <24000000>;   
        reg = <1>;   
        compatible = "rohm,dh2228fv";        
    }; 
 
}; 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值