linux at24测试程序,linux 2.6下eeprom at24c08 i2c设备驱动(new style probe方式)

1 修改bsp_以便支持probe

1.1 AT24C08地址的确定

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png原理图上将A2、A1、A0都接地了,所以地址是0x50。

注意到是7位(bit).

1.2 修改bsp

采用友善之臂的, 2.6.32.2内核

[root@localhost mach-s3c2440]# vim

/opt/FriendlyARM/mini2440/linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c

#include

static struct platform_device *mini2440_devices[] __initdata =

{

&s3c_device_usb,

&s3c_device_rtc,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c0, //没有修改

&s3c_device_iis,

&mini2440_device_eth,

&s3c24xx_uda134x,

&s3c_device_nand,

&s3c_device_sdi,

&s3c_device_usbgadget,

}; //这里没有修改

static struct at24_platform_data at24c08 = {

.byte_len = SZ_8K / 8,

.page_size = 16,

}; //add

static struct i2c_board_info i2c_devices[] __initdata = {

{ I2C_BOARD_INFO("at24c08b", 0x50),

.platform_data = &at24c08, //不可少的

},

}; //add

#if 0

static struct i2c_board_info i2c_devices[] __initdata = {

{ I2C_BOARD_INFO("at24c08b", 0x50),

.irq=43, //不用.platform_data = &at24c08, 用这个也行

//从cat /proc/interrupt中可知

},

}; //TESTED BY awaken_ing#163

#endif

static void __init mini2440_machine_init(void)

{

i2c_register_board_info(0,i2c_devices,ARRAY_SIZE(i2c_devices));

//add

#if defined (LCD_WIDTH)

s3c24xx_fb_set_platdata(&mini2440_fb_info);

#endif

s3c_i2c0_set_platdata(NULL);

s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);

s3c_device_nand.dev.platform_data =

&friendly_arm_nand_info;

s3c_device_sdi.dev.platform_data =

&mini2440_mmc_cfg;

platform_add_devices(mini2440_devices,

ARRAY_SIZE(mini2440_devices));

s3c_pm_init();

}

然后make -j2 (传说的多任务, 这里是2个任务, 速度快点)进行编译内核

1.3 编译内核, 然后u-boot部分

#/opt/study_arm/u-boot-2009.11_ok_no_nand/tools/mkimage -A arm -O

linux -T kernel -C none -a 30008000 -e 30008040 -n linux_awaken -d

/opt/FriendlyARM/mini2440/linux-2.6.32.2/arch/arm/boot/zImage

/opt/study_arm/uImage_mini_2.img

#nfs 30008000

192.168.0.9:/opt/study_arm/uImage_mini_2.img

#setenv bootargs noinitrd root=/dev/nfs rw

nfsroot=192.168.0.9:/opt/FriendlyARM/mini2440/rootfs_qtopia_qt4/

ip=192.168.0.2:192.168.0.1::255.255.255.0 console=ttySAC0,115200

init=/linuxrc mem=64M

#bootm 0x30008000

1.4 启动linux后

[root@FriendlyARM /home]# ls /dev|grep i2

i2c

这是原先的

[root@FriendlyARM /home]# mknod /dev/at24c08b c 250 0

要mknod的, 不是insmod后产生的, (我傻傻地在这折腾了好久)

[root@FriendlyARM /home]# ls /dev|grep 24

at24c08b

tty24

2 驱动程序

#include #include

#include

#include

#include

#include

#include

#include

#include#include

#define AT24C08B_MAJOR 250

static int at24c08b_major = AT24C08B_MAJOR;struct at24c08b_dev

{

struct

i2c_client *client;

char

name[30];

unsigned

short current_pointer;

struct cdev

cdev;};

struct at24c08b_dev *at24c08b_devp;

static intat24c08b_open (struct inode *inode, struct file

*file)

{

file->private_data =

at24c08b_devp;

return

0;}

static ssize_tat24c08b_read (struct file *file, char *buf, size_t count, loff_t *

ppos)

{

int i =

0;

int

transferred = 0;

int ret,

my_buf[512];

struct

at24c08b_dev *dev = (struct at24c08b_dev *)

file->private_data;

dev->current_pointer =

*ppos;

if

(i2c_check_functionality

(dev->client->adapter,

I2C_FUNC_SMBUS_READ_BYTE_DATA))

{

while

(transferred <

count)

{

ret =i2c_smbus_read_byte_data

(dev->client,

dev->current_pointer +

i); my_buf[i++] = (unsigned short) ret;

transferred += 1;}

copy_to_user

(buf, (void *) my_buf,

transferred);

dev->current_pointer +=

transferred;

}

return

transferred;}

static ssize_tat24c08b_write (struct file *file, char *buf, size_t count, loff_t

* ppos)

{

int i =

0;

int

transferred = 0; int ret, my_buf[512];

struct at24c08b_dev *dev = (struct at24c08b_dev *)

file->private_data;dev->current_pointer =

*ppos;

if

(i2c_check_functionality (dev->client->adapter,

I2C_FUNC_SMBUS_BYTE_DATA))

{

copy_from_user (my_buf, buf,

count);

while

(transferred <

count)

{

ret =i2c_smbus_write_byte_data

(dev->client,

dev->current_pointer +

i,

my_buf[i]);

i += 1;

transferred += 1;

}

dev->current_pointer +=

transferred;

}

return

transferred;}

static intat24c08b_ioctl (struct inode *inodep, struct file *file, unsigned

int cmd, unsigned long arg)

{

return

0;}

static intat24c08b_release (struct inode *inodep, struct file

*file)

{

file->private_data =

NULL;

return

0;}

static const struct file_operations at24c08b_fops = {.owner =

THIS_MODULE,

.open =

at24c08b_open,

.read =

at24c08b_read,

.write =

at24c08b_write,

.ioctl =

at24c08b_ioctl,

.release =

at24c08b_release,};

static voidat24c08b_setup_cdev (struct at24c08b_dev *dev, int

index)

{

int err,

devnum = MKDEV (at24c08b_major,

index);

cdev_init

(&dev->cdev,

&at24c08b_fops);

dev->cdev.owner =

THIS_MODULE;

err =

cdev_add (&dev->cdev, devnum,

1);

if

(err)

printk

(KERN_NOTICE "Error %d adding at24c08b %d", err,

index);}

static int __devinitat24c08b_probe (struct i2c_client *client, const struct

i2c_device_id *id)

{

int

ret;

printk

(KERN_NOTICE "at24c08b probe is

start\n"); //调试用,看是否执行了probe 函数 dev_t devnum = MKDEV (at24c08b_major, 0);

if (at24c08b_major)ret =

register_chrdev_region (devnum, 1,

"at24c08b");

else

{

ret =

alloc_chrdev_region (&devnum, 0, 1,

"at24c08b");

at24c08b_major = MAJOR

(devnum);

}

if (ret

< 0)

return

ret;

at24c08b_devp = kmalloc (sizeof (struct at24c08b_dev),

GFP_KERNEL);

if

(!at24c08b_devp)

{

ret =

-ENOMEM;

goto

fail_malloc;

} memset (at24c08b_devp, 0, sizeof (struct at24c08b_dev));

at24c08b_devp->client = client;

at24c08b_setup_cdev (at24c08b_devp, 0);

return 0;

fail_malloc: unregister_chrdev_region (devnum, 1);

return ret;}

static int __devexitat24c08b_remove (struct i2c_client

*client)

{

cdev_del

(&at24c08b_devp->cdev);

kfree

(at24c08b_devp); unregister_chrdev_region (MKDEV (at24c08b_major, 0), 1);

return 0;}

static const struct i2c_device_id at24c08b_id[] = {{"at24c08b",

0}, //这个0是不是有点奇怪啊, 呵呵

{}};

MODULE_DEVICE_TABLE (i2c, at24c08b_id);static struct i2c_driver at24c08b_driver =

{

.driver =

{

.name = "at24c08b",

.owner = THIS_MODULE,

},

.probe =

at24c08b_probe,

.remove =

__devexit_p

(at24c08b_remove),

.id_table =

at24c08b_id,};

static int __initat24c08b_init (void)

{

printk

(KERN_NOTICE "at24c08b is

insmod\n");

return

i2c_add_driver

(&at24c08b_driver);}

voidat24c08b_exit (void)

{

printk

(KERN_NOTICE "at24c08b is

rmmod\n");

i2c_del_driver

(&at24c08b_driver);}

MODULE_DESCRIPTION ("at24c08b eeprom driver");MODULE_LICENSE ("Dual

BSD/GPL");

MODULE_AUTHOR ("Weimeng Li "); //不是我, 我是awaken_inghttp://blog.163.com/awaken_ing/MODULE_VERSION ("V1.0");

module_param (at24c08b_major, int, S_IRUGO);

module_init (at24c08b_init);module_exit (at24c08b_exit);

3 用户程序

#include #include

#include

#include

#include#include

int main(int argc, char **argv){

int i;

unsigned int value[512];

value[0] = 0x12;

value[1] = 0x23;

value[2] = 0x34;

value[3] = 0x45;

value[4] = 0x56; value[5] = 0x67;

int fd;fd = open("/dev/at24c08b",

O_RDWR);

if(fd < 0)

{

printf("Open at24c08b Device

Faild!\n");

exit(1); }

write(fd, value, 6);for(i = 0; i < 6;

i++)

printf("write reg[%d] data: %x to at24c08\n", i,

value[i]);

printf("#########################################\n"); sleep(1);

read(fd, value, 6);for(i = 0; i < 6;

i++) printf("read reg[%d] data: %x to at24c08\n", i, value[i]);

close(fd);return

0;}

4 makefile

#Makefile#变量APP、DEV分别用于配置用户程序/驱动程序

*文件名*

APP=app_i2c

DEV=i2c_no_fops

ifneq ($(KERNELRELEASE),)

#call from kernel build

system

obj-m:=$(DEV).o

else

KERNELDIR

?=/opt/FriendlyARM/mini2440/linux-2.6.32.2

PWD :=$(shell pwd)

default:

$(MAKE) -C

$(KERNELDIR) M=$(PWD)

modules

cp $(DEV).ko

/opt/FriendlyARM/mini2440/rootfs_qtopia_qt4/home

#for

app,根据变量APP是否为空来处理

ifneq ($(APP),)

arm-linux-gcc -Wall $(APP).c -o

$(APP)

cp $(APP)

/opt/FriendlyARM/mini2440/rootfs_qtopia_qt4/home

endifendif

clean:rm -rf

*.ko

rm -rf

*.o rm -rf *.mod.*

#注意到$(APP).c会正确得到解析.

5 测试

[root@FriendlyARM /home]# mknod /dev/at24c08b c 250 0

[root@FriendlyARM /home]# insmod dev_i2c.ko

at24c08b is insmod

at24c08b probe is start

[root@FriendlyARM /home]# ./app_i2c

write reg[0] data: 12 to at24c08

write reg[1] data: 23 to at24c08

write reg[2] data: 34 to at24c08

write reg[3] data: 45 to at24c08

write reg[4] data: 56 to at24c08

write reg[5] data: 67 to at24c08

#########################################

read reg[0] data: 12 to at24c08

read reg[1] data: 23 to at24c08

read reg[2] data: 34 to at24c08

read reg[3] data: 45 to at24c08

read reg[4] data: 56 to at24c08

read reg[5] data: 67 to at24c08

参考文章

linux文档 Documentation/i2c/upgrading-clients

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值