电子开发网
您的位置电子开发网>嵌入式系统>

S3C44b0的IIC(AT24C04)的uclinux驱动

时间:2007-01-25   来源:   作者:   点击:……  字体大小:【

       看了很多书上写的44b0的IIC的驱动都是很难理解的那种,都是照抄三星的程序的,于是就自己改写了IIC的驱动,我认为这样有助于理解执行的过程,很简单易懂.
/*
*iic.c:
* read and write only one byte for AT24C04
*/
#i nclude <asm/hardware.h>
#i nclude <linux/module.h>
#i nclude <linux/fs.h>
#i nclude <linux/types.h>
#i nclude <linux/malloc.h>
#i nclude <asm/uaccess.h>
#i nclude <asm/page.h>
#i nclude <linux/errno.h>
#i nclude <linux/config.h>
#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<<7)|(0<<6)|(1<<5)|(0xf));    //Enable interrupt, IICCLK=MCLK/16, Enable ACK
    //40Mhz/16/(15+1) = 257Khz
  CSR_WRITE(rIICADD,0x10);   // S3C44B0X slave address
 CSR_WRITE(rIICSTAT,0x10);
  
 CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_IIC));  // Clear EINT's  Pending Bit
  CSR_WRITE(rINTMSK,(CSR_READ(rINTMSK)&(~BIT_IIC)));  // Enable interrupt

 ret = register_chrdev(IIC_MAJOR,"iic",&IIC_fops);
 if(ret<0) {
   printk("fail to register\n");
   }
 CLEAR_PEND_INT(IIC_IRQ);
 
 if(IIC_IRQ >=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<i)
 {
  cm++;
  }
 }


Tags:S3C44B0   驱动   IIC    
  • 关于本站 - 联系我们 - 网站地图 - 网站留言 - 返回顶部