- 论坛徽章:
- 0
|
IIC驱动
我使用的开发板,处理器芯片44B0与EEPROM(24C08)通过iic总线连接,因此验证IIC驱动,就是通过写入C08一个数据然后再从中读出的方法。我使用中断的方法来实现IIC数据的传输,查询的方法其实与中断差不多,应该更简单一些。
下面是我的驱动程序
#include
#include
#include
//#include
#include
#include
#include
#include 3c44b0x.h>
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#define IIC_MAJOR 254
#define NAME "eeprom"
#define pdataf *(volatile unsigned char *)S3C44B0X_PDATAF
#define pconf *(volatile unsigned char *)S3C44B0X_PCONF
#define pupf *(volatile unsigned char *)S3C44B0X_PUPF
#define i2ccon *(volatile unsigned char *)S3C44B0X_IICCON
#define i2cstat *(volatile unsigned char *)S3C44B0X_IICSTAT
#define i2caddr *(volatile unsigned char *)S3C44B0X_IICADD
#define i2cds *(volatile unsigned char *)S3C44B0X_IICDS
static DECLARE_WAIT_QUEUE_HEAD(wait);
#include
#include
//void s3c44b0x_mask_irq(unsigned int irq);
//void s3c44b0x_clear_pb(unsigned int irq);
void s3c44b0x_mask_irq(unsigned int irq)
{
outl( inl(S3C44B0X_INTMSK) | ( 1 3C44B0X_INTMSK);
}
void s3c44b0x_clear_pb(unsigned int irq)
{
outl( (1 3C44B0X_I_ISPC);
}
//extern void s3c44b0x_mask_irq(unsigned int irq);
//extern void s3c44b0x_unmask_irq(unsigned int irq);
//extern void s3c44b0x_clear_pb(unsigned int irq);
//extern void s3c44b0x_mask_ack_irq(unsigned int irq);
static ssize_t i2cread (struct file *filp,char *buf,size_t count,loff_t *offp);
static ssize_t i2cwrite(struct file *filp,const char *buf,size_t count,loff_t *offp);
static int i2crelease(struct inode *inode,struct file *filp);
static int i2copen(struct inode *inode,struct file *filp);
static char condition = 0;
static struct file_operations iic_fops = {
open:i2copen,
read:i2cread,
write:i2cwrite,
release:i2crelease,
};
//byte write
static ssize_t i2cwrite(struct file *filp,const char *buf,size_t count,loff_t *offp)
{
/****************** transmit the slave address **********************/
condition = 0;
i2cds = 0xa0;
i2cstat = 0xf0; //MasTx,start,En Tx/Rx,
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
// interruptible_sleep_on(&wait);
condition = 0;
/***************** transmit the address of where to write ************/
i2cds = buf[0]; //the write address
i2ccon = 0xe2; //resume iic operation
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
/***************** write the data ************************************/
i2cds = buf[1];
i2ccon = 0xe2; //resume iic operation
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
/***************** stop trans ***************************************/
i2cstat = 0xd0; //MasTx,stop,En Tx/Rx,
i2ccon = 0xe2; //resume iic operation
udelay(1000);
return (2);
}
//this is a random read (24c08)
static ssize_t i2cread (struct file *filp,char *buf,size_t count,loff_t *offp)
{
/****************** transmit the slave address **********************/
condition = 0;
i2cds = 0xa0;
i2cstat = 0xf0; //MasTx,start,En Tx/Rx,
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
/***************** transmit the address of where to read ************/
i2cds = 0x74; //the read address
i2ccon = 0xe2; //resume iic operation
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
buf[0] = i2cds;
/***************** read the data ************************************/
i2cds = 0xa1; //read address
i2cstat = 0xb0; //MasRx,start,En Tx/Rx,
i2ccon = 0xe2; //resume iic operation
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
i2ccon = (0xe2 & (~0x80));
wait_event_interruptible(wait, (condition != 0)); //wait the trans complete
condition = 0;
buf[1] = i2cds;
printk("the read data = %x | %x\n",buf[0],buf[1]);
/***************** stop trans ***************************************/
i2cstat = 0x90; //MasRx,stop,En Tx/Rx,
i2ccon = 0xe2; //resume iic operation
udelay(1000);
return (2);
}
void iic_irq(int irq, void *dev_id, struct pt_regs *regs)
{
if(i2cstat & 0x04)
printk("slave address received\n");
printk("iicaddress = %x \n",i2caddr);
condition = 1;
printk("interrupt\n");
wake_up_interruptible( &wait );
s3c44b0x_clear_pb( S3C44B0X_INTERRUPT_IIC );
}
static int i2copen(struct inode *inode,struct file *filp)
{
int ret;
unsigned long flag;
ret = request_irq(S3C44B0X_INTERRUPT_IIC,iic_irq,SA_INTERRUPT,"iic",NULL);
if(ret
{
printk("iic interrupt request failed!\n");
free_irq(S3C44B0X_INTERRUPT_IIC,NULL);
return ret;
}
local_irq_save(flag);
pconf &= 0xfff0; //config the io
pconf |= 0x000a; //iicsda iicsdl
pupf &= 0xfc;
i2caddr = 0x10;
i2ccon = 0xe2; //ack, enable interrupt,Fiiclk=Fmclk/512=117k,
i2cstat = 0x10; //en rx/tx
// i2caddr = 0xa0;
local_irq_restore(flag);
MOD_INC_USE_COUNT;
return ret;
}
static int i2crelease(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
s3c44b0x_mask_irq(S3C44B0X_INTERRUPT_IIC);
free_irq(S3C44B0X_INTERRUPT_IIC,NULL);
return 0;
}
static int __init i2c_init(void)
{
int ret;
ret = register_chrdev(IIC_MAJOR,NAME,&iic_fops);
if(ret
{
printk("eeprom device register failed");
return ret;
}
return 0;
}
static void __exit i2c_exit(void)
{
int ret;
ret = unregister_chrdev(IIC_MAJOR,NAME);
if (ret
{
printk("eeprom device unregister failed");
return;
}
printk("iic device uninstalled!\n");
}
module_init(i2c_init);
module_exit(i2c_exit);
现在这个驱动实现了uclinux下的读写功能,但是其中还有一点还没弄明白。为什么这个iicaddr寄存器写入0xa0后,状态标志寄存器的地址匹配标志位不致“1”,如果哪位看客有高见,谢谢你的指点。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21839/showart_147651.html |
|