历史上的今天
返回首页

历史上的今天

今天是:2024年12月30日(星期一)

正在发生

2021年12月30日 | 4412 SPI驱动

2021-12-30 来源:eefocus

1.Linux主机驱动和外设驱动分离思想(I2C驱动里有)

SPI驱动总线架构:SPI核心层(x),SPI控制器驱动层(x),SPI设备驱动层(√)。前面两个设备驱动搞明白了可以去看

 

2.教程中介绍:SPI函数接口(API):

简单介绍SPI协议,硬件原理(4412datasheet)

 

3.教程中介绍:SPI函数接口(API):

简单介绍SPI协议,硬件原理(4412datasheet)

  • SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)

  • SPI(rfid模块)的硬件基础知识(增加reset)

  • SPI CLK管脚复用:Android4.0(wifi不能用)

 

  • rfid的驱动配置:

    • Device Drivers

    • →SPI support

    • →SPI_RC522

  • can的驱动配置:

  • Networking support

    • →CAN bus subsystem support

    • →CAN Device Drivers

  • Platform CAN drivers with Netlink support(默认配置,不用动)

  • CAN_MCP251X

 

设备注册:spi_board_info,spi_register_board_info

驱动注册函数和结构体:spi_register_driver/spi_unregister_driver,spi_driver

读写函数和结构体:spi_transfer和spi_message结构体,spi_async

 

1.驱动“设备注册,驱动注册,probe,数据下传,数据上传”的小结

虚拟平台:

①因为LED,蜂鸣器等等,因为这些驱动本身不是总线。所以都注册在虚拟平台总线上(platform_device)。

②然后platfrom_driver_register就是在驱动程序中使用了,注册时的platfrom_driver结构体中有name成员对应platform_device的名字。此结构当然还有probe,remove,suspend,resume等配套的功能接口。

③然后对LED来说,GPIO的操作基本是在probe中初始化。

④然后应用层如果需要调用,那么在probe里就需要注册杂项设备、字符设备等。


I2C:

①I2C的设备注册和平台注册类似,都是在arc/arm/mach-exynos/mach-itop4412.c中完成的

②和平台设备类似,I2C使用的函数不一样罢了,而且结构体也是i2c_driver了

③I2C对硬件的传输,使用i2c_transfer结合i2c_msg

④然后应用层如果需要调用,那么需要注册杂项设备,和虚拟平台类似。


SPI:

基本和I2C类似不同的是操作硬件的函数,spi_transfer要配置一下,然后传输用spi_sync。SPI让应用层调用使用字符设备。

 

2.设备-SPI设备注册一级设备注册之后的查询方法

配置SPI的内核之后可以用,查询到


[root@iTOP-4412]# cat sys/bus/spi/devices/spi2.0/modalias                              

rc522


SPI_board_info参数


spi_board_info参数

    .modalias = "rc522",    //初始化设备的名称

    .platform_data = NULL,    

    .max_speed_hz = 10*1000*1000,    //初始化传输速率

    .bus_num = 2,        //控制器编号

    .chip_select = 0,    //控制器片选的编号

    .mode = SPI_MODE_0,    //spi的模式

    .controller_data = &spi2_csi[0],    //片选IO的信息


spi2_board_info设备描述结构体,设备注册函数spi_register_board_info

 

增加一个spi设备my_rc522,然后去掉rfid和can驱动

mach-itop4412.c

/* add by cym 20141222 for RC522 RFID */

#ifdef CONFIG_SPI_RC522

        {

                .modalias = "rc522",

                .platform_data = NULL,

                .max_speed_hz = 10*1000*1000,

                .bus_num = 2,

                .chip_select = 0,

                .mode = SPI_MODE_0,

                .controller_data = &spi2_csi[0],

        }

#endif

/* end add */

/* add by ct 2018825 */

        {

                .modalias = "my_rc522",

                .platform_data = NULL,

                .max_speed_hz = 10*1000*1000,

                .bus_num = 2,

                .chip_select = 0,

                .mode = SPI_MODE_0,

                .controller_data = &spi2_csi[0],

        }

/* end add */


cat sys/bus/spi/devices/spi2.0/modalias
rfid的设备名称my_rc522

 

3.驱动-spi驱动注册和卸载。I2C设备初始化完成-进入probe函数。(不能加载wifi驱动)

my_rc522.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#include

#include


#include


#include

#include

#include

#include


static int __devinit my_rc522_probe(struct spi_device *spi)

{

    /* reset */

    printk(KERN_EMERG "my_rc522_probe!n");



    return 0;

}


static int __devexit my_rc522_remove(struct spi_device *spi)

{

    printk(KERN_EMERG "my_rc522_remove!n");

    return 0;

}


static struct spi_driver my_rc522_spi_driver = {

    .driver = {

        .name = "my_rc522",

        .owner = THIS_MODULE,

    },

    .probe = my_rc522_probe,

    .remove = __devexit_p(my_rc522_remove),

};


static int __init my_rc522_init(void)

{

    spi_register_driver(&my_rc522_spi_driver);

    return 0;

}


static void __exit my_rc522_exit(void)

{

    spi_unregister_driver(&my_rc522_spi_driver);

}


module_init(my_rc522_init);

module_exit(my_rc522_exit);


MODULE_AUTHOR("topeet: ct");

MODULE_LICENSE("GPL");


4.驱动-spi数据的传输(rfid模块,不能加载wifi驱动)

  • 1.本节实验需要RFID的硬件模块

  • 2.1平台文件中RC522的设备名称直接改为my_rc522

  • 2.2需要配置rfid对应的menuconfig

  • 2.3 drivers/spi/Makefile中注释掉rc522.c文件的编译

  • 3.从rc522驱动中提取spi传输的核心代码

  • 4.直接在probe中做复位,读,写测试

    • 写:rc522_write→rc522_sync_write→rc522_sync→spi_async

    • 读:rc522_read→rc522_sync_read→rc522_sync→spi_async

my_rc522

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#include "spidev_test.h"

#include "spidev.h"


struct spi_device *my_spi;


#define RC522_RESET_PIN    EXYNOS4_GPK1(0)

void my_rc522_reset()

{

    //printk("************************ %sn", __FUNCTION__);

    if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))

                pr_err("failed to request GPK1_0 for RC522 reset controln");


        s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);

        gpio_set_value(RC522_RESET_PIN, 0);


        mdelay(5);


        gpio_set_value(RC522_RESET_PIN, 1);

        gpio_free(RC522_RESET_PIN);

}



static int write_test(unsigned char *buffer, int len)

{

    int status;

    struct spi_transfer    t = {

        .tx_buf        = buffer,

        .len        = len,

    };

    struct spi_message    m;

    spi_message_init(&m);

    spi_message_add_tail(&t, &m);

    DECLARE_COMPLETION_ONSTACK(done);

    m.complete = complete;

    m.context = &done;

    

    printk("spi_async send begin!n");

    status = spi_async(my_spi,&m);

    if(status == 0){

        wait_for_completion(&done);

        status = m.status;

        if (status == 0)

            status = m.actual_length;

    }

    return status;

}


static int read_test(unsigned char *buffer, int len)

{

    int status;

    struct spi_transfer    t = {

        .rx_buf        = buffer,

        .len        = len,

    };

    struct spi_message    m;

    spi_message_init(&m);

    spi_message_add_tail(&t, &m);

    DECLARE_COMPLETION_ONSTACK(done);

    m.complete = complete;

    m.context = &done;

    

    printk("spi_async read begin!n");

    status = spi_async(my_spi,&m);

    if(status == 0){

        wait_for_completion(&done);

        status = m.status;

        if (status == 0)

            status = m.actual_length;

    }

    return status;

}


static unsigned char ReadRawRC(int addr)

{

    int ret;

    unsigned char  ReData;

    unsigned char  Address;

    

    Address  = (unsigned char)addr << 1;

    Address |= (1 << 7);

    Address &= ~(1 << 0);

    

    ret = write_test(&Address, 1);

    if (ret < 0)

        printk("spi:SPI Write errorn");


    udelay(100);


    ret = read_test(&ReData, 1);

    if (ret < 0)

        printk("spi:SPI Read errorn");


    return ReData;

}


static int WriteRawRC(int addr, int data)

{

    int ret;

    unsigned char  TxBuf[2];


    //bit7:MSB=0,bit6~1:addr,bit0:RFU=0

    TxBuf[0] = ((unsigned char)addr << 1)&0x7E;

    //TxBuf[0] &= 0x7E;


    TxBuf[1] = (unsigned char)data;

    

    ret = write_test(TxBuf, 2);

    

    if (ret < 0)

        printk("spi:SPI Write errorn");


    udelay(10);


    return ret;

}



static int rc522_init()

{

    int ret;

    char version = 0;


    //reset

    WriteRawRC(CommandReg, PCD_RESETPHASE);

    udelay(10);

    WriteRawRC(ModeReg, 0x3D);

    WriteRawRC(TReloadRegL, 30);

    WriteRawRC(TReloadRegH, 0);

    WriteRawRC(TModeReg, 0x8D);

上一篇:4412 Linux定时器

下一篇:4412 i2c驱动

推荐阅读

史海拾趣

Adam Tech公司的发展小趣事

Adam Tech公司成立于1987年,总部位于美国新泽西州。创业初期,公司面临着资金短缺、市场竞争激烈等诸多困难。然而,创始人凭借对电子连接器行业的深刻理解和执着追求,带领团队克服重重困难,逐渐在市场上站稳脚跟。公司最初的产品线相对单一,但凭借着高品质和可靠的性能,逐渐赢得了客户的信任。

GS Technology公司的发展小趣事
用于显示电信号的波形和峰值。
Holt Integrated Circuits公司的发展小趣事

除了传统的航空电子解决方案外,Holt还致力于高压LCD显示驱动器的研发。这些产品不仅满足了航空电子设备对高可靠性和高清晰度的需求,还广泛应用于工业过程自动化和井下钻探等领域。Holt的高压LCD显示驱动器以其卓越的性能和稳定性,赢得了众多客户的信赖和好评。

Hewlett Packard Co公司的发展小趣事
采用性能优良的差分电路作放大电路,使得电路的信噪比和动态范围达到了较高的技术水平。
ABB Group公司的发展小趣事
负反馈的引入有助于减小电路的失真,提高音质表现。
Antenova公司的发展小趣事

Antenova公司积极寻求与其他行业领导者的战略合作,以推动公司的成长和发展。通过与全球知名的芯片制造商、设备生产商等建立合作关系,Antenova得以将其天线产品集成到更广泛的电子产品中,从而进一步扩大了市场份额。这些战略合作不仅提升了Antenova的品牌知名度,还为公司的长期发展提供了有力支持。

以上是关于Antenova公司发展起来的五个相关故事,这些故事展示了公司在技术创新、市场拓展、产品推出、专业服务以及战略合作等方面的努力和成就。这些成就为Antenova在电子行业中的成功奠定了坚实基础,并为公司未来的持续发展提供了有力保障。

问答坊 | AI 解惑

超声波发射接收器

超声波发射接收器换能器    有正负之分么????…

查看全部问答>

按键专题活动总结---准备做一个按键学习的开发板

在3月份我们在论坛搞了一个按键专题活动的讨论(https://bbs.eeworld.com.cn/viewthread.php?tid=97931 ),这个活动获得了大家的广泛支持,讨论的很是热烈根据讨论内容,从大家的讨论中,我们学习和了解到了更多的按键方面的知识。 俗话说的好: ...…

查看全部问答>

sdram,nor flash,nand flash

各位大侠,小弟刚接触嵌入式。有些基本的问题还没有搞清楚,请教一下 在一块板子上,有sdram,nor flash,nand flash 哪个是用来存储系统的, 这3个又有什么区别呢?…

查看全部问答>

wince跑程序老是报错!

C:\\Program Files\\Microsoft eMbedded C++ 4.0\\Common\\EVC\\MyProjects\\2\\2.cpp(4) : fatal error C1083: Cannot open precompiled header file: \'emulatorDbg/2.pch\': No such file or directory 随便什么程序,都是报这个错误,这是为什 ...…

查看全部问答>

2011年全国竞赛基本仪器和主要元器件清单

本帖最后由 paulhyde 于 2014-9-15 09:47 编辑 …

查看全部问答>

这是什么错误,很奇怪

keil编译时,提示入下错误:(我估计不应该是程序的错误,不知道哪里没有设置正确)   Build target \'Target 1\'assembling STARTUP.A51...compiling Lcd.c...C51 FATAL-ERROR -  ACTION:     GOBAL OPTIMIZATION ...…

查看全部问答>

初学者的迷惑

我今年准备开始学习430,之前只有一点单片机的知识,感觉学习起来没有压力,对C语言算是了解了,不算透彻但是感觉应付单片机够了。 现在就有一个疑问,学习430需要哪些储备知识才能很好的上手(尽量详细一点)!这个问题一直很疑惑,主要实验室现 ...…

查看全部问答>

beaglebone心得一:windows下驱动安装

我收到的就一个SD卡,但带了个SD大卡卡槽。并不是传说中的,两个SD卡。 我破不急等地插到USB口上,当然迷你SD卡也插上,发现硬件。我等着自动装硬件。但显示了一个虚拟的U盘。我又傻等一会儿,还是要驱动。 应是U转串的驱动。 我查型号是FT2232H ...…

查看全部问答>

煤矿井下主排水泵安全保护装置设计(毕业论文)

主要要求:1.本系统负责对主排水泵的电压、电流、轴瓦温油温、润滑油油压、水泵真空度等一系列参数进行测量并显示。2.系统能自动根据所测量得到的参数进行综合逻辑分析,判断是否出现异常情况,并在异常情况出现时自动启动继电器接口来控制相应的节 ...…

查看全部问答>