免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1012 | 回复: 0
打印 上一主题 下一主题

IIC驱动 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-07-30 10:42 |只看该作者 |倒序浏览

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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP