中断处理程序
{
清除中断
硬件自动清除
软件清除
}
CPU芯片手册相关章节
————————
I2C
CPU外接设备的方式
1)GPIO简洁的方式(按键,LED)
通过设置GPIO管脚的状态来完成通信(控制)
gpccon
gpcpud
gpcdat
2)类似于内存的接口 (DDRAM norflash nand dm9000)
从硬件上看CPU和芯片 数据线 地址先 BANK
3)协议类接口
uart
I2C
AT24C02 EEPROM
3,如何解决CPU和设备通信的问题
I2C通信协议:定义:两线式串行总线 SCL:时钟线 SDA:数据线
通信过程中使用到的信号
start:处于高电平 在SCL处于高电平SDA有个下降沿;
stop:处于低电平 在SCL处于高电平SDA有个上升沿;
ACK: 应答信号,在SCL处于高电平SDA为低电平时;
在SCL可以变数据,在SCL为高不能改变SDA
I2C通信特点
I2C通信过程中,设备之间有主从之分。
在开发板上I2C总线上的主设备就是CPU(可配置)
挂在I2C总线上的其他 芯片统统是从设备
I2C通信的发起者肯定是主设备
I2C总线上的每个从设备都有一个固定的地址。
4.EEPROM驱动开发
AT24C02容量,结合原理图,找到开发板上的地址,如何写(读)一个字节到该芯片
2Kbits 256字节 1010xxxx
写
start信号
7位地址+w
等待应答
word address:发送要写入的地址
等待应答
发送即将写入的数据
等待应答
产生信号
读:
START信号
从设备地址+w
等待信号
start信号
发从设备内存地址—R
等待ACK
接收从设备发送的字节的数据
第九周期两种方式:回复ACK 第10周期 从设备继续发送下一个存储的数据
不发ACK 第10周期设备休息
主设备 STOP
cpu里有个I2C core.c
我们要做的就是实现device i2c_client
i2c_new_device 在链表加上节点
device_driver i2c_driver i2c_add_driver 在链表添加节点
然后调用下match函数执行probe函数 再通过I2C协议完成CPU和芯片的通信
AT24C02驱动程序
按照总线驱动模型来写
实现一个i2c_client 和
i2c_driver
{
要访问AT24C02
调用I2C控制器启动程序(数据交互)
}
I2C控制器的驱动程序(内核中已实现了)
send
recv
AT24C02程序
添加i2c_cliend
Documentation\i2c\instantiating-devices
vi arch/arm/mach-xxxxxx/mach-xxxxx.c
static stuct i2c_board_info i2c_at24cxx[] =
{
{I2C_BOARD_INFO("at24cxx",0x50)
},
};
c参数1:名称 参数二:从设备地址
i2c_register_board_info(0,i2c_at24cxx,ARRAY_SIZE(i2c_at24cxx));
解释:0:cpu的I2C不止一个,也就是有很多i2c接口,看原图看看它挂在哪个接口 才确定是几
2)添加driver
i2c_transfer()i2c收发数据函数
AT24C02模块主要程序:
#include <linux/i2c.h>
#include <linux/uaccess.h>
dev_t dev;
struct艾24cxxx_dev
{
struct cdev cdev;
struct i2c_client *client;
}
struct class *dev_class = NULL;
struct device dev_device NULL;
struct at24cxx_dev *at24cxx_devp =NULL;
static int xxxxxx_prob (struct i2c_client *client,const struct i2c_device_id *id)
{
申请设备号
alloc_chrdev_region(&dev,0,"xxxxx");
申请cdev空间
at24cxx_devp =kzalloc(sizeof(struct at24cxx),GFP_KERNEL);
at24cxx_devp->client =clirnt;
初始化cdev并添加到内核
cdev_init(&at24cxx_devp->cdev,&ar24cxx_fops);
cdev_add(at24cxx_devp->cdev,dev,1);
创建设备节点文件
dev_class-class_create(THIS_...,"AT24CXX");
dev_device = device_create(dev_class,NILL,dev
NULL,"AT24CXX0");
}
int at24cxx_remove(struct i2c_client *client)
{
device_destroy()dev_class,dev);
class_destroy(dev_class);
cdev_del(&at24cxx_devp);
kfree(at24cxx_devp);
unregister_chrdev_region(dev,1);
return 0;
}
static size_t at24cxx_write(struc file *file,char __user buf,size_size,loff_t *offset)
{
unsigned char val[2];
struct i2c_msg msg[1];
int ret =0;
if(size ! -2)
{
return -1
}
copy_from_user(。。。);
msg[0].add=at24cxx->client->addr//从设备地址
msg[0].flags=0;//写入
msg[0].buf =val;//数据
msg[0].len =2;
//START ....ADDR+W ACK offset ACK val ACK
i2c_transfer( ar24cxx_devp->client->adapter,msg,1);//内核创建的adapter 在
//i2c_register_board_info()中;
return 2;
}
static ssize_t xxxx_read(struc file *file,char __user buf,size_size,loff_t *offset)
{
unsigner char address;
unsigned char data;
struct i2c_msg msg[2];
int ret;
ret = copy_form_user(&address,buf,1);
msg[0].addr=at24cxx_devp->client->addr;
msg[0]=flags = 0;
msh[0].buf=&address;
msh[0].len =1;
msg[0].addr=at24cxx_devp->client->addr;
msg[0]=flags = 1;//读信号
msh[0].buf=&data;
msh[0].len =1;
i2c_transfer( ar24cxx_devp->client->adapter,msg,ARRAY_SIZR(msg));//内核创建的adapter 在
//i2c_register_board_info()中;
ret =cop_to_user();
}
struct filr_operations at24cxx_fops =
{
.owner = ....,
.read = at24cxx_read,
.write = at24cxx_write,
}
const struct i2c_device_id id_table[] =
{
{"at24cxx",0},
{ }//结束标志
}
struct i2c_driver at24cxx_driver =
{
.driver=
{
.name="AT24C02"
.owner=...
},
.probe = xxxxxxxxxx,
.remove = xxxxxxxxxx,
.id_table = at24cxx_id //i2c match 会使用到,来匹配能支持那些设备
};
__int
i2c_add_driver(&at24cxx_driver);
__exit
i2c_del_driver(&at24cxx_driver);
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/typer,h>
#include <sys/stat.h>
#include <fcntl.h>
void print_rsage(char*file)
{
printf("%s r addr\n"file);
printf(% w addr val\n,file);
}
int main (int argc , char **argv)
{
int fd;
unsigned char buf[2];
if(argc!=3 &&argc!=4)
{
print_usage(argv[0]);
return -1;
}
fd=open(/dev/ar24cxx0",O_RDWR)
if(strcmp(argv[1],"r")==0)
{
buf[0]=strtoul(artoul[2],NULL,0);
read(fd,buf,1);
peintf(data %c %s 0x%2x\n,buf[0]....);
}
else if(sstrcmp(argv[1],"w")==0)
{ buf[0]=strtoul(artoul[2],NULL,0);
buf[1]=strtoul(artoul[3],NULL,0);
write(fd,buf,2);
}
else
{
print_usage(argv[0]);
return -1
}
return 0;
}
本文出自 “毛散人” 博客,请务必保留此出处http://songmao.blog.51cto.com/11700139/1880431
原文地址:http://songmao.blog.51cto.com/11700139/1880431