历史上的今天
今天是: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驱动
史海拾趣
|
在3月份我们在论坛搞了一个按键专题活动的讨论(https://bbs.eeworld.com.cn/viewthread.php?tid=97931 ),这个活动获得了大家的广泛支持,讨论的很是热烈根据讨论内容,从大家的讨论中,我们学习和了解到了更多的按键方面的知识。 俗话说的好: ...… 查看全部问答> |
|
各位大侠,小弟刚接触嵌入式。有些基本的问题还没有搞清楚,请教一下 在一块板子上,有sdram,nor flash,nand flash 哪个是用来存储系统的, 这3个又有什么区别呢?… 查看全部问答> |
|
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 随便什么程序,都是报这个错误,这是为什 ...… 查看全部问答> |
|
keil编译时,提示入下错误:(我估计不应该是程序的错误,不知道哪里没有设置正确) Build target \'Target 1\'assembling STARTUP.A51...compiling Lcd.c...C51 FATAL-ERROR - ACTION: GOBAL OPTIMIZATION ...… 查看全部问答> |
|
我收到的就一个SD卡,但带了个SD大卡卡槽。并不是传说中的,两个SD卡。 我破不急等地插到USB口上,当然迷你SD卡也插上,发现硬件。我等着自动装硬件。但显示了一个虚拟的U盘。我又傻等一会儿,还是要驱动。 应是U转串的驱动。 我查型号是FT2232H ...… 查看全部问答> |
|
主要要求:1.本系统负责对主排水泵的电压、电流、轴瓦温油温、润滑油油压、水泵真空度等一系列参数进行测量并显示。2.系统能自动根据所测量得到的参数进行综合逻辑分析,判断是否出现异常情况,并在异常情况出现时自动启动继电器接口来控制相应的节 ...… 查看全部问答> |




