?? 44b0-iic-drive.txt
字號:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/arch/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/s3c44b0x.h>
#include "config.h"
#include "44b.h"
#define IIC_MAJOR 232
#define IIC_NAME "xiuiic"
#define S3C44B0X_INTERRUPT_IIC 5
#define XIUIIC_DEBUG
static DECLARE_WAIT_QUEUE_HEAD(wait);
volatile uint8 I2C_sla = 0xa0; //從機地址
volatile uint8 I2C_suba = 0x00; //子地址
volatile uint8 iic_usage = 0;
volatile uint8 ack_tag;
volatile uint8 I2cReadWrite;
#undef PDEBUG /* undef it, just in case */
#ifdef XIUIIC_DEBUG
# ifdef __KERNEL__
/* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_INFO "xiuiic: " fmt, ## args)
# else
/* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif
static void board_init()
{
rPDATF = 0X0;
rPCONF = (rPCONF&0xfffffff0)|0x0a; //SDA,SCL
rPUPF = rPUPF|0x3; //disable SDA and SCL pull up
rSYSCFG=SYSCFG_8KB;
}
void vdelay(unsigned short i)
{
ushort cm = 0;
while(cm < i)
{
cm++;
}
}
static int iic_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
return(0);
}
static loff_t iic_llseek(struct file *filp,loff_t off,int whence)
{
return(0);
}
static ssize_t iic_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
// char ker_buf;
char *ker_buf;
char *ptr;
int i; //the number of data truly read
I2cReadWrite=0;
ack_tag = 0;
PDEBUG( "enter to read function\n");
if ((ker_buf = kmalloc(count,GFP_KERNEL)) == NULL) //dynamic allocation
PDEBUG("kmalloc error\n");
ptr = ker_buf;
PDEBUG( "start to transfer slave addr 0xa0\n");
rIICDS = I2C_sla; // 0xa0
rIICSTAT = 0xf0; // Master Tx,Start
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
// PDEBUG("start to transfer sub-addr 0x00\n");
rIICDS = I2C_suba;
rIICCON = 0xe2; // resumes IIC operation.
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
// PDEBUG("start to transfer slave addr 0xa1\n");
rIICDS = I2C_sla|0x01; // 0xa1:Read
rIICSTAT=0xb0; // Master Rx,Start
rIICCON=0xe2; // resumes IIC operation.
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
*ptr = rIICDS; //ack from slave device
//begin to loop???????????應該把ack清零嗎?
PDEBUG("start to transfer data\n");
for (i = 1; i < count; i++) //only read count-1 data
{
rIICCON = 0xe2; //????????????????rIICCON = 0xe2 & (~0x80)
wait_event_interruptible(wait, (ack_tag != 0));
ack_tag = 0;
*ptr = rIICDS;
PDEBUG("readbuf[%d] = %c\n", i, *ptr);
ptr++;
}
//PDEBUG("the first data in buf is %d\n", user_buf[0]);
rIICCON = 0xe2 & (~0x80) ;//disable ack,the last data disable ack
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
PDEBUG("the last data in rIICDS is %c\n", rIICDS);
*ptr = rIICDS; //read the last data
rIICSTAT = 0x90;//write this register,so send stop signal
rIICCON = 0xe2;//resume IIC operation
vdelay(100);
copy_to_user(buf, ker_buf, i); //if i=1 < count means not read a part of data
rI_ISPC = rI_ISPC | BIT_IIC;//CLEAR PENDING BIT OF IIC TO MEAN IT IS FREE
kfree(ptr);
return(i);
}
static int iic_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
char *ker_buf;
char *ptr;
int i; //the data
//char ker_buf;
PDEBUG("entering write function\n");
if ((ker_buf = kmalloc(count,GFP_KERNEL)) == NULL) //dynamic allocation
PDEBUG("kmalloc error\n");
copy_from_user(ker_buf, buf, count);
ptr = ker_buf;
ack_tag = 0;
I2cReadWrite=1;
//rIICSTAT=0x10; // enbale TX/RX
rIICDS = I2C_sla; // 0xa0
rIICSTAT=0xf0; // Master Tx,Start
PDEBUG("start to transfer the addr of slave device\n");
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
PDEBUG("start to transfer the sub-addr\n");
rIICDS = I2C_suba;
rIICCON = 0xe2; // resumes IIC operation.
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
// begin to write
PDEBUG("start to transfer data\n");
for (i = 0; i <count; i++)
{
rIICDS = *ptr;
rIICCON = 0xe2; // resumes IIC operation.
wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete
ack_tag = 0;
PDEBUG("buf[%d] = %c\n", i, rIICDS);
ptr ++;
}
PDEBUG("begin to end\n");
rIICSTAT = 0xd0; // stop Master Tx condition
rIICCON = 0xe2; // resumes IIC operation.
PDEBUG("we have write %d numbers in to epprom\n", i);
rI_ISPC = rI_ISPC | BIT_IIC;//CLEAR PENDING BIT OF IIC TO MEAN IT IS FREE
vdelay(100);
kfree(ptr);
return(i);
}
static void iic_irq(int irq, void *dev_id,struct pt_regs *regs)
{
ack_tag = 1;
wake_up_interruptible(&wait);
rI_ISPC = rI_ISPC | BIT_IIC;
}
static int iic_open(struct inode *inode,struct file *filp)
{
int ret;
unsigned long flag = 0;
if (iic_usage == 0)
{
ret = request_irq(S3C44B0X_INTERRUPT_IIC,iic_irq,SA_INTERRUPT,IIC_NAME,NULL);
if (ret)
{
PDEBUG("%s: iic driver irq request failed.\n",IIC_NAME);
free_irq(S3C44B0X_INTERRUPT_IIC,NULL);
return(ret);
}
}
PDEBUG("%s: request irq success.\n", IIC_NAME);
local_irq_save(flag);
board_init();
rIICADD = 0x10;//slave addr
//IIC operation configure
rIICCON=0xe2; //Enable ACK,interrupt, IICCLK=MCLK/512, Enable ACK//64Mhz/512/(9+1) = 12.5Khz
rIICSTAT = 0x10; // enbale TX/RX
PDEBUG("before INTPND = %d\n", rINTPND);
rI_ISPC = rI_ISPC | BIT_IIC;//CLEAR PENDING BIT OF IIC TO MEAN IT IS FREE
PDEBUG("after INTPND = %d\n", rINTPND);
//init_waitqueue_head(&wait);
PDEBUG("before mask = %d\n", rINTMSK);
rINTMSK = rINTMSK & ~BIT_IIC;// & ~BIT_GLOBAL;//ENABLE IIC AND GLOBAL INTERRUPT
PDEBUG("after mask = %d\n", rINTMSK);
local_irq_restore(flag);
iic_usage ++;
PDEBUG("iic_usage is %d\n",iic_usage);
MOD_INC_USE_COUNT;
return(0);
}
static int iic_release(struct inode *inode,struct file *filp)
{
unsigned long flag = 0;
vdelay(100);
MOD_DEC_USE_COUNT;
if(iic_usage)iic_usage --;
if(iic_usage==0)
{
local_irq_save(flag);
//PDEBUG("INTPND = %d\n", rINTPND);
//rI_ISPC = rI_ISPC | BIT_IIC;//CLEAR PENDING BIT OF IIC TO MEAN IT IS FREE
//PDEBUG("INTPND = %d\n", rINTPND);
//rINTMSK = rINTMSK | BIT_IIC;
local_irq_restore(flag);
free_irq(S3C44B0X_INTERRUPT_IIC,NULL);
PDEBUG("enter release\n");
}
return(0);
}
static struct file_operations iic_fops={
// owner:THIS_MODULE,
llseek:iic_llseek,
read: iic_read,
write: iic_write,
open: iic_open,
release:iic_release,
ioctl:iic_ioctl,
};
static int __init myiic_init(void)
{
int result;
result=register_chrdev(IIC_MAJOR,IIC_NAME,&iic_fops);
if(result==0){
PDEBUG("%s: iic driver installed.\n", "myiic");
return 0;
}
PDEBUG("%s:IIC driver install fail.\n","myiic");
return(result);
}
static void __exit myiic_exit(void)
{
int ret;
ret = unregister_chrdev(IIC_MAJOR,IIC_NAME);
if (ret < 0)
{
PDEBUG( KERN_ALERT "unregister fail\n");
return;
}
PDEBUG(KERN_ALERT "leddrv:good_bye!\n");
}
module_init(myiic_init);
module_exit(myiic_exit);
/******************************************************************************************
測試程序
********************************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
int
main(int argc, char **argv)
{
int fd;
int count = 16;
char wbuf[16] = "mingming shi zhu";
char rbuf[16];
char *ptr;
int i;
// printf("enter main\n");
// printf("\n");
if ((fd = open("/var/tmp/ming/driver/IIC_test/xiuiic", O_RDWR)) == -1)
{
perror("open error\n");
exit(1);
}
printf("open ok\n");
printf("fd = %d\n",fd);
// printf("%s\n", wbuf);
// fflush((void *)STDOUT_FILENO);
if (write(fd, wbuf, count) != count)
{
perror("write error\n");
exit(1);
}
printf("we have write %d characters\n", count);
//test write by reading
if (read(fd, &rbuf, count) != count)
{
perror("read error\n");
exit(1);
}
ptr = rbuf;
for ( i = 0; i < count; i++)
{
printf("read[%d] = %c\n", i, *ptr);
ptr ++;
}
printf("\n");
close(fd);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -