- 论坛徽章:
- 0
|
看了很多书上写的44b0的IIC的驱动都是很难理解的那种,都是照抄三星的程序的,于是就自己改写了IIC的驱动,我认为这样有助于理解执行的过程,很简单易懂.
/*
*iic.c:
* read and write only one byte for AT24C04
*/
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude "IIC.h"
void vdelay(unsigned short i);
static DECLARE_WAIT_QUEUE_HEAD(wait);
unsigned char WrData= 0 ;
unsigned char RecvData[2] = {0,0};
volatile static unsigned char ack_tag;
volatile static unsigned int addr;
static int IIC_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) //count读取的数量;
{
//printk("read addr %d \n",addr);
/****************** 读** 写入设备地址 **********************/
ack_tag = 0;
CSR_WRITE(rIICDS,0xa0); //设备地址
CSR_WRITE(rIICSTAT,0xf0); //MasTx,start,En Tx/Rx,
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/***************** 读**写入读取的低地址 ************/
CSR_WRITE(rIICDS,(char)addr); //the read address
CSR_WRITE(rIICCON,0xaf); //resume iic operation
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/****************** 读**再次写入设备地址 **********************/
CSR_WRITE(rIICDS,0xa0); //设备地址
CSR_WRITE(rIICSTAT,0xb0); //MasRx,start,En Tx/Rx,
CSR_WRITE(rIICCON,0xaf); //resume iic operation
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/***************** read the data ************************************/
RecvData[1]=CSR_READ(rIICDS); //这次读到的没有用
CSR_WRITE(rIICCON,0x2f); //只读一位
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
RecvData[0]=CSR_READ(rIICDS);
printk("read data %d \n",RecvData[0]);
/***************** stop trans ***************************************/
CSR_WRITE(rIICSTAT,0x90); //MasRx,stop,En Tx/Rx,
CSR_WRITE(rIICCON,0xaf); //resume iic operation
vdelay(100);
copy_to_user(buf, &RecvData, sizeof(char));
return (1);
}
static int IIC_write(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
//unsigned int i;
if(copy_from_user(&WrData, buf, sizeof(char)))
{
printk("error writing, copy_from_user\n");
return -EFAULT;
}
printk("write address %d \n",addr);
printk("write data %d \n",WrData);
/****************** 写** 写入设备地址 **********************/
ack_tag = 0;
CSR_WRITE(rIICDS,0xa0);
CSR_WRITE(rIICSTAT,0xf0); //MasTx,start,En Tx/Rx,
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/***************** 写** 写入存储器的内部地址低位 ************/
CSR_WRITE(rIICDS,(char)addr); //the write high address
CSR_WRITE(rIICCON,0xaf); //resume iic operation
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/***************** write the data ************************************/
CSR_WRITE(rIICDS,WrData); //the write high address
CSR_WRITE(rIICCON,0xaf); //resume iic operation
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
/***************** stop trans ***************************************/
CSR_WRITE(rIICSTAT,0xd0); //MasTx,stop,En Tx/Rx,
CSR_WRITE(rIICCON,0xaf); //resume iic operation
vdelay(100);
return (1);
}
static int IIC_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
addr = arg;
return 1;
}
static int IIC_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
printk("someone open iic!\n");
return 0;
}
static int IIC_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
printk("someone close iic\n");
return 0;
}
static int IIC_select(struct file *file,struct poll_table_struct *wait)
{
return 0;
}
void IIC_handle(int irq,void *dev_id,struct pt_regs *regs)
{
//char rec;
//rec = CSR_READ(rIICDS);
//printk(" \n %d \ n",rec);
CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_IIC)); // Clear IIC Pending Bit
ack_tag = 1;
wake_up_interruptible(&wait);
}
void IIC_init(void)
{
int ret;
CSR_WRITE(rPCONF,((CSR_READ(rPCONF)&0xfffffff0)|0xa)); //PF0:IICSCL,PF1:IICSDA
CSR_WRITE(rPUPF,(CSR_READ(rPUPF)|0x3));//禁止内部上拉
CSR_WRITE(rIICCON,0xaf);//(1=0){
ret = request_irq(IIC_IRQ,IIC_handle,SA_INTERRUPT,"IICS",NULL);
if(ret){
printk("IIC:cant get assigned irq %i\n",IIC_IRQ);
}
else{
printk("IIC:request external interrupt %i\n",IIC_IRQ);
INT_ENABLE(IIC_IRQ);
}
}
}
void vdelay(unsigned short i)
{
ushort cm=0;
while(cm
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/82516/showart_1849544.html |
|