mini2440 i2c设备支持

发布者:BlossomSunrise最新更新时间:2021-11-24 来源: eefocus关键字:mini2440  i2c 手机看文章 扫描二维码
随时随地手机看文章

内核版本:linux-2.6.32.2  实验平台:mini2440


1. 添加主控设备支持

i2c主控制器也是一个设备,只是在内核被虚拟成了一个平台设备,平台设备在内核中已经被定义了,定义在plat-s3c/dev-i2c0.c中:

static struct resource s3c_i2c_resource[] = {

[0] = {

.start = S3C_PA_IIC,

.end   = S3C_PA_IIC + SZ_4K - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = IRQ_IIC,

.end   = IRQ_IIC,

.flags = IORESOURCE_IRQ,

},

};

 

struct platform_device s3c_device_i2c0 = {

.name   = "s3c2410-i2c",

#ifdef CONFIG_S3C_DEV_I2C1

.id   = 0,

#else

.id   = -1,

#endif

.num_resources   = ARRAY_SIZE(s3c_i2c_resource),

.resource   = s3c_i2c_resource,

};

那么我只需要将这个平台设备添加到mini2440_devices这个数组里面,最终这个平台设备将被注册到内核中。


2. 添加主控驱动支持

主控制器驱动为drivers/i2c/busses/i2c-s3c2410.c,那么我们只需要配置一下就可以了:

   Device Drivers  --->

<*> I2C support  --->

I2C Hardware Bus support  --->

<*> S3C2410 I2C Driver


3. at24c08 i2c设备的注册

这里使用i2c_register_board_info()函数来注册i2c设备,首先是使用I2C_BOARD_INFO宏来定义i2c设备信息:

static struct at24_platform_data at24_platdata = {

.byte_len = 8192,

.page_size = 16,

};

 

static struct i2c_board_info mini2440_i2c_devices[] = {

{

I2C_BOARD_INFO("24c08", 0x50),

.platform_data = &at24_platdata,

}

};

mini2440上at24c08的i2c地址为0x50,并且是挂载到i2c0上的,在mini2440_machine_init去完成注册:

i2c_register_board_info(0, mini2440_i2c_devices, ARRAY_SIZE(mini2440_i2c_devices));

其中的第一个参数需要注意,为i2c的总线号。


最后还需要注意别忘了包含这两个头文件:


4. at24c08驱动支持

驱动代码就用默认的drivers/misc/eeprom/at24.c,配置如下:

    Device Drivers  --->

[*] Misc devices  ---> 

EEPROM support  --->

-*- I2C EEPROMs from most vendors


5. 验证

那么怎么去验证我们添加的i2c驱动和i2c设置是匹配成功的了呢,进入到这个目录下:/sys/bus/i2c/drivers/at24,然后可以看到一个文件0-0050,说明i2c驱动和i2c设备是匹配成功了的。

//2016.3.27 add

linux自带的eeprom驱动程序可能不便于测试,为此,我写了个简单的i2c驱动用来测试at24c08,代码如下:


#include

#include

#include

#include

#include

#include

#include

 

MODULE_LICENSE("GPL");

 

struct at24_data {

struct cdev cdev;

struct i2c_client *client;

};

 

int at24_read_block(struct i2c_client *client,

u8 addr, u8 len, u8 *values)

{

return i2c_smbus_read_i2c_block_data(client, addr, len, values);

}

 

int at24_write_block(struct i2c_client *client,

u8 addr, u8 len, u8 *values)

{

return i2c_smbus_write_i2c_block_data(client, addr, len, values);

}

 

#define BLOCK_MAX 32

 

static size_t at24_read(struct file *file, char __user *buf,

size_t count, loff_t *pos)

{

struct at24_data *at24 = file->private_data;

int num;

u8 block[BLOCK_MAX];

 

if (count > BLOCK_MAX)

count = BLOCK_MAX;

 

num = at24_read_block(at24->client, *pos, count, block);

 

if (copy_to_user(buf, block, num)) {

return -EFAULT;

} else {

*pos += num;

return num;

}

}

 

static size_t at24_write(struct file *file, char __user *buf,

size_t count, loff_t *pos)

{

struct at24_data *at24 = file->private_data;

int num;

u8 block[BLOCK_MAX];

 

if (count > BLOCK_MAX)

count = BLOCK_MAX;

 

if (copy_from_user(block, buf, count)) {

return -EFAULT;

} else {

num = at24_write_block(at24->client, *pos, count, block);

 

*pos += num;

return num;

}

}

 

static size_t at24_open(struct inode *inode, struct file *file)

{

struct at24_data *at24;

 

at24 = container_of(inode->i_cdev, struct at24_data, cdev);

file->private_data = at24;

return 0;

}

 

static size_t at24_close(struct inode *inode, struct file *file)

{

file->private_data = NULL;

return 0;

}

 

static struct file_operations at24_fops = {

.open = at24_open,

.release = at24_close,

.read = at24_read,

.write = at24_write,

};

 

static int at24_probe(struct i2c_client *client,

const struct i2c_device_id *id)

{

struct at24_data *at24;

int retval = 0;

dev_t dev_id;

 

at24 = kzalloc(sizeof(struct at24_data), GFP_KERNEL);

if (!at24) {

return -ENOMEM;

}

 

at24->client = client;

 

retval = alloc_chrdev_region(&dev_id, 0, 1, "at24c08");

if (retval < 0) {

dev_err(&client->dev,

"unable to allocate char device regionn");

goto err_out;

}

 

cdev_init(&at24->cdev, &at24_fops);

 

retval = cdev_add(&at24->cdev, dev_id, 1);

if (retval < 0) {

dev_err(&client->dev,

"unable to register char devicen");

goto err_free_region;

}

 

i2c_set_clientdata(client, at24);

 

return 0;

err_free_region:

unregister_chrdev_region(dev_id, 1);

err_out:

kfree(at24);

return -1;

}

 

static int at24_remove(struct i2c_client *client)

{

struct at24_data *at24 = i2c_get_clientdata(client);

 

cdev_del(&at24->cdev);

kfree(at24);

unregister_chrdev_region(at24->cdev.dev, 1);

 

return 0;

}

 

static struct i2c_device_id at24_ids[] = {

{ "at24c08", 0 },

{ }

};

MODULE_DEVICE_TABLE(i2c, at24_ids);

 

static struct i2c_driver at24_driver = {

.driver = {

.name = "at24c08",

},

.id_table = at24_ids,

.probe = at24_probe,

.remove = at24_remove,

};

 

static int __init at24_init(void)

{

return i2c_add_driver(&at24_driver);

}

 

static void __exit at24_exit(void)

{

i2c_del_driver(&at24_driver);

}

 

module_init(at24_init);

module_exit(at24_exit);

编译好了之后,首先insmod,然后mknod,测试app程序如下:

#include

#include

#include

#include

#include

#include

 

//#define TEST_WRITE 1

#define TEST_READ 1

 

int main(int argc, char *argv[])

{

int fd;

int i;

char buf[8];

 

if (argc < 2)

exit(1);

 

fd = open(argv[1], O_RDWR);

if (fd < 0)

exit(1);

 

#ifdef TEST_WRITE

for (i = 0; i < sizeof(buf); i++)

buf[i] = i;

write(fd, buf, sizeof(buf));

#endif

 

#ifdef TEST_READ

memset(buf, 0, sizeof(buf));

 

read(fd, buf, sizeof(buf));

for (i = 0; i < sizeof(buf); i++)

printf("%d ", buf[i]);

printf("n");

#endif

 

close(fd);

exit(0);

}


最后测试得即使掉电之后也能正确读取到写入的数据,说明程序是ok的。

// 2016-05-15 add

另一个i2c read函数


int at24_read_array(struct i2c_client *client,

u8 addr, u8 len, u8 *vals)

{

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 1,

.buf = &addr

},

{

.addr = client->addr,

.flags = I2C_M_RD,

.len = len,

.buf = vals

}

};

int ret;

 

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

if (ret < 0)

printk("i2c_transfer errorn");

 

return ret;

}


这里使用i2c_transfer来操作i2c,注意i2c_transfer的返回值,正确返回的是传输i2c_msg的个数。

关键字:mini2440  i2c 引用地址:mini2440 i2c设备支持

上一篇:ARM时钟学习
下一篇:mini2440裸机之I2C

推荐阅读最新更新时间:2024-11-09 10:30

eCos在mini2440 Qemu的网络功能测试
终于可以方便的用mini2440 qemu的网络功能了, 大家参考一下雪松的这篇帖子《QEMU MINI2440 的 Linux Fedora 8 下网络配置 》http://www.linuxidc.com/Linux/2011-09/42195.htm 既然可以这样用了,我重新整理了mini2440的redboot 1. 根据qemu对dm9000模拟的限制,对dm9000驱动程序做了新的修改 2. ecos的看家绝技,gdb调试应用程序 根据雪松的修改,现在可以用arm-eabi-gdb 的target remote来做ecos 应用程序的单步调试了 3. ecos的httpd 在mini2440 qemu的测试
[单片机]
eCos在<font color='red'>mini2440</font> Qemu的网络功能测试
mini2440烧写裸机程序(linux+supervivi+dnw)
一、编写源程序(init.S、testledC.lds、testledC.c、Makefile) @****************************************************************************** @ File:init.S @ 功能:通过它转入C程序 @****************************************************************************** .text .global _start _start: ldr r0, =0x53000000 @ WATCHDOG寄存器地址
[单片机]
U-Boot-1.1.6移植到MINI2440开发板(1) —— 移植前分析
将U-Boot-1.1.6移植到MINI2440开发板上,从NAND Flash启动(不使用NOR Flash)。 需要准备的: Linux环境:Ubuntu 16.04 交叉编译工具链:arm-linux-gcc-3.4.5 U-Boot-1.1.6源码:u-boot-1.1.6.tar.bz2 S3C2440手册:S3C2440A 32-BIT CMOS MICROCONTROLLER USERS MANUAL ARM920T技术手册:ARM920T Technical Reference Manual 其它相关datasheet 参考资料:《嵌入式Linux应用开发完全手册》以及网上博客(#^.^#)。 说明:下述涉
[单片机]
uboot-2012.04.01移植到mini2440(一)启动流程、内存分布及重定位初步分析
编译环境:ubuntu9.10 uboot版本:u-boot-2012.04.01 开发平台:mini2440 u-boot-2012.04.01启动流程: 1. 设置为管理模式 2. 关闭看门狗 3. 关中断 4. 设置时钟分频比 5. 跳转到cpu_init_crit执行 a. 禁止MMU、关闭caches b. 跳入到lowlevel_init执行 *. 初始化内存控制器 6. 设置堆栈,为跳入board_init_f做准备 a. 跳入board_init_f执行 *. board_init_f函数中进行了各种初始化,并重新设置了堆栈,为重定位代码做准备 *. 调用
[单片机]
uboot-2012.04.01移植到<font color='red'>mini2440</font>(一)启动流程、内存分布及重定位初步分析
linux2.6.32.2 mini2440平台移植-- LCD 显示驱动 ( W35屏 )
1.4.1 LCD 驱动基础知识 Linux-2.6.32.2 内核已经支持 S3C2440 的 LCD 控制器驱动,但在此我们先介绍一下关于 2440 LCD 控制器以及驱动相关的 LCD 的一些基础知识。 注意:在此我们只讨论 TFT LCD,也就是真彩屏。 LCD 驱动中最关键的就是时钟频率(Clock frequency)的设置,时钟频率设置不对,LCD 的显示就会闪,或者根本没有显示。一般 LCD 的 Datasheet 上会写有一个推荐的频率,比如 mini2440 所用的统宝 3.5 LCD,在它的数据手册第 13 页,有这样一个表格:可以看到,这里推荐的时钟频率是 6.39MHz,近似于 6.4MHz,
[单片机]
U-boot移植到mini2440
本文章中的很多内容参考友善之臂的说明文档《mini2440之U-boot移植详细手册-20100419》,使用的U-boot的版本是u-boot-2010.03 说明:此次移植的目的不是为了制作一个功能强大的U-boot,只是做一个最简单的U_boot。该U-boot能够实现通过串口和电脑通信,可以将环境变量保存在NOR Flash中,通过TFTP服务器将使用NFS根文件系统的内核镜像从电脑拷贝到内存中执行。而且这个U-boot只支持从NOR中启动。 在移植U-Boot之前建议对U-Boot中的源码组织结构有较深的理解,可参考我的另一篇博文Bootloader介绍和Uboot源码结构 移植U-Boot的原则是,先选取与
[单片机]
mini2440LED驱动程序开发
/*********************************************************实验源代码 ********************************************************************/ 一、源代码: /***********************mini2440_leds.c*********************** *******************************************************************/ #include linux/miscdevice.h #include
[单片机]
u-boot-2011.03在mini2440/micro2440上的移植 支持DM9000
3.1 include/configs/micro2440.h 删除 #define CONFIG_CS8900 /* we have a CS8900 on-board */ #define CONFIG_CS8900_BASE 0x19000300 #define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */ #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 10.0.0.110 #define CONFIG_SERVERIP 10.0.0.1 添加 #defi
[单片机]
u-boot-2011.03在<font color='red'>mini2440</font>/micro2440上的移植 <font color='red'>支持</font>DM9000
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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