4412 SPI驱动

发布者:钱老李最新更新时间:2022-01-29 来源: eefocus关键字:SPI驱动  I2C驱动 手机看文章 扫描二维码
随时随地手机看文章

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);

[1] [2] [3] [4] [5] [6] [7] [8]
关键字:SPI驱动  I2C驱动 引用地址:4412 SPI驱动

上一篇:4412 Linux定时器
下一篇:4412 i2c驱动

推荐阅读最新更新时间:2024-11-10 12:52

串口编程(基于tiny4412
参考: http://www.cnblogs.com/wblyuyang/archive/2011/11/21/2257544.html http://www.cppblog.com/amazon/archive/2010/01/28/106644.html serial_demo.c #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h //文件控制定义 #include termios.h //终端控制定义 #include errno
[单片机]
N76E003 驱动 ST7567 (SPI串口)
再看DXP原理图(+Bat为3.3V),LCD_Rst为硬件复位引脚,如不需要可直接设为高电平。BG_V/BG_G为背光端,单片机控制背光可使用三极管。 初始化流程 对比度调节 COG.c文件代码 #include N76E003.h #include SFR_Macro.h #include Function_define.h #include Common.h #include Delay.h #include intrins.h #include COG.h #include LCDFont.h #define Page0 0xb0 //第0页地址 #define Page_max 0
[单片机]
N76E003 <font color='red'>驱动</font> ST7567 (<font color='red'>SPI</font>串口)
STM32 SPI驱动TFT LCD
利用STM32F030 的SPI驱动TFT LCD,我使用的LCD为240*320像素的2.4寸彩屏,驱动IC为ili9341,只需四根线即可点亮LCD,先贴上SPI配置吧,声明一下,F030的SPI配置和F103等的配置有些不一样 /*LCD SPI Init*/ void SPI_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; SPI_InitTypeDef SPI_InitStructure; /* Enable the SPI periph */ RCC_APB1PeriphClock
[单片机]
tiny4412 串口驱动分析三 --- log打印的几个阶段之内核自解压
开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 u-boot:U-Boot 2010.12 Linux内核版本:linux-3.0.31 Android版本:android-4.1.2 内核自解压时期的串口打印 在zImage格式的内核启动时会自解压内核,此时打印信息如下: Uncompressing Linux... 这句话是在arch/arm/boot/compressed/misc.c中: void decompress_kernel(unsigned long output_start, unsigned lo
[单片机]
tiny<font color='red'>4412</font> 串口<font color='red'>驱动</font>分析三 --- log打印的几个阶段之内核自解压
tiny4412学习(四)之移植linux-设备树(1)设备树基础知识及中断
硬件平台:tiny4412 系统:linux-4.4 文件系统:busybox-1.25 编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320) uboot:友善自带uboot. 一、DTS引入 1.什么是DTS?为什么要引入DTS? DTS即Device Tree Source设备树源码,DeviceTree是一种描述硬件的数据结构,它起源于OpenFirmware (OF)。 在Linux2.6中,ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,比如板上的platform设备、reso
[单片机]
tiny<font color='red'>4412</font>学习(四)之移植linux-设备树(1)设备树基础知识及中断
SPI接口的16位AD7705驱动程序
最近在做一个印度项目时,应用到16位AD转换器AD7705,此器件是AD公司推出的双通道16位 - (电荷平衡式)A/D转换器。具有高分辨率、宽动态范围、自校准,低功耗及优良的抗噪声性能,因此非常适用于仪表测量和工业控制等领域。16位无丢失代码;0.003%的非线性度;内部放大器可选择1,2,4,8,16,32,64,128;8种增益;输出数据更新速率可编程;具有自校准和系统校准功能,三线串行接口,可缓冲模拟输入;低功耗。经努力,目前已调通一个通道,现将驱动程序共享,愿起到抛砖引玉的作用。此程序在项目板上调试通过,而且测试精度极高,显示的电压值准确稳定。 #include iom16v.h #include macros.h #
[单片机]
Exynos4412的外部中断是如何安排的?
平台 Linux4.9 tiny4412 概述 结合tiny4412开发板分析一下Exynos4412的外部中断是如何组织的。 在Exynos4412的用户手册第9章Interrupt Controller列出了支持的外部中断: 第1列是按Shared Peripheral Interrupt 排序的 第2列是按Software Generated Interrupt + Peripheral Interrupt(PPI+SPI)排序的, 目前GIC提供了16个SGI中断和16个PPI中断 从上面可以看到,硬件上提供了32个外部中断,但是我们在第6章的GPIO Control一节说: 图2 上面说,有172个外
[单片机]
Exynos<font color='red'>4412</font>的外部中断是如何安排的?
mini2440 I2C驱动的分析与学习(二)
接着分析i2c的数据传输流程。 首先是打开i2c设备,比如open( /dev/i2c/0 ),在内核调用下面函数 static int i2cdev_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct i2c_client *client; struct i2c_adapter *adap; struct i2c_dev *i2c_dev; int ret = 0; lock_kernel(); i2c_dev = i2c_dev_get_by_min
[单片机]

推荐帖子

13、Beaglebone外围电路设计第四周:关于AM335x 的浮点型使用的心得体会!!
设计来到了第四周,这一周,我用StellarisGraphicsLibrary设计了数据采集的LCD界面,这个会在下一个帖子里和大家分享!我这次要讲的是关于AM335x的浮点型使用的心得体会,我的设计里面要加入显示倾角的表盘,这个我在M4的活动里做过这个界面https://bbs.eeworld.com.cn/viewthread.php?tid=330039,所以我以为会很容易实现的!!可是调程序就是这样,你永远不会知道自己会碰到什么!!这次我就碰到了!!首先,我是在程序里面
anananjjj DSP 与 ARM 处理器
脉冲功率装置能源计算机控制技术
脉冲功率装置能源计算机控制技术摘要介绍一种多分布传式MARX发生器能源计算机监控系统.详细叙述了系统的硬件构成,计算机与各能源系统之间的通讯原理和通讯协议,以及系统的软件实现,同时简要说明了系统抗干扰解决办法。关键词MARX发生器程控电源RS485总线VisualBasic脉冲功率装置能源计算机控制技术
mdreamj 工控电子
大家谈谈都用什么板子啊?(被坑的分数要回来了,散分!)
我想了解一下大家现在都在用什么开发板啊,将来准备用什么开发板呢?能总是谈技术,总要看看未来吧,想做个统计,看看啥是当前主流,将来的趋向是什么。另外,也欢迎大家谈谈对CE前景的看法大家谈谈都用什么板子啊?(被坑的分数要回来了,散分!)最初用了下三星SMDK2450的开发板了解了一下,然后直接拿的产品demo板做东西。以后有机会的话找块6410的板子玩玩。2440我还是去年买的优龙的2440具体要看做什么用了!!!引用4楼ankye的回复:具体要看做什么用了!!!
yuexiaomei 嵌入式系统
国外老师用microbit教逻辑门
国外一个老师使用microbit教学生学习逻辑门电路。Iwantedahandsonwaytoteachlogicgatesandtruthtablestomystudents,soIdecidedtoprogramasetofmicrobitstoactlikelogicgates.Theselogicgatescouldthenbeconnectedtoswitchesandoutputsusing
dcexpert MicroPython开源版块
拆解一个WSN的节点设备,看看如何选料?
物联网的兴起带旺了很多新兴的技术和产品,无线传感网络(WirelessSensorNetwork,简称WSN)就是其中之一。对于WSN最简单的理解就是,将传统的传感器技术和网络通讯融合在一起,让物联网节点同时具备感知和通信能力,使无处不在的传感器不再是各自为战的数据孤岛,而是构成一个可靠、高效、智能的数据生产和传输体系,因此WSN也被认为是物联网的核心支撑技术之一。不过WSN这个概念说起来简单,但在实际设计过程中并不是将已有功能电路和模块简单地拼凑在一起,还是会遇到很多新的挑战。
ohahaha RF/无线
从零开始仿制工业PLC
从零开始仿制工业PLC不错的想法,不过PLC没有必要用这么高级的芯片。zhaojun_xf发表于2015-8-2212:23不错的想法,不过PLC没有必要用这么高级的芯片。 打算后期增加新功能,当然,量产时看实际情况了。这个主意不错的这个好我要支持点个赞,加油!“我要参与”,本人对工业控制和PLC比较熟悉,多年从事工业控制,设计过多款工业控制板。谢谢大家支持做PLC,顺便自带工业屏!我要支持我要支持@boming建议最好简单介绍一下你自己的项
boming stm32/stm8
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved