写了个IIC键盘驱动有些错误,大牛们过来看看能否解决,同时功能上是否能实现!

wilson0913 2008-04-30 05:37:09
附件里面我放了源代码,同时也将源代码帖到下面:

/*IIC键盘程序:CPU是S3C2440,嵌入式操作系统是linux2.6.13,IIC键盘芯片是ZLG7290(周立功的片子);硬件中断连接方法,
将ZLG7290的INT按键中断引脚接GPF2(将GPF2配置成中断功能EINT2),当有按键按下时,ZLG7290的INT引脚产生中断,CPU接受中断
通过IIC读取ZLG7290的01H寄存器,01H寄存器存放键值。
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/arch/irqs.h>

#include <linux/input.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/signal.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-irq.h>
#include <asm/dma.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>


#ifndef __ZLG7290_H__
#define __ZLG7290_H__

#define WRDATA (1)
#define POLLACK (2)
#define RDDATA (3)
#define SETRDADDR (4)

#define IICBUFSIZE 0x20

//ZLG7290 SlaveAddress
#define ZLG7290_SlaveADDR 0x70 //IIC从设备地址

//ZLG7290 Register
#define ZLG7290_SystemReg 0x00 //系统寄存器
#define ZLG7290_Key 0x01 //获取键值寄存器地址,复位为00H
#define ZLG7290_RepeatCnt 0x02 //按键重复按的次数

#endif


#define DEVICE "IIC_ZLG7290"
#define BIT_IIC (0x1<<27)

int major = 233;
int minor = 0;
void *R_GPECON,*R_GPEUP,*R_GPFCON,*R_GPFUP,*R_EXTINT0,*R_IICCON,*R_IICSTAT,*R_IICADD,*R_IICDS;


#define U8 unsigned char
#define U32 unsigned int
static unsigned char _iicData[IICBUFSIZE];
static volatile int _iicDataCount;
static volatile int _iicStatus;
static volatile int _iicMode;
static int _iicPt;
static int flag = 0;
struct work_struct Iic_wq; //工作队列

void Iic_do_work(unsigned long);//中断处理底半部函数
void _Rd2410Iic(U32 slvAddr,U32 addr,U32 *rdata);
void Run_IicPoll(void);
void IicPoll(void);
static U8 Getkey_zlg7290(void);

int IIC_open(struct inode *, struct file *);
int IIC_release(struct inode *, struct file *);
ssize_t IIC_read(struct file *file, char* buf, size_t count, loff_t *f_pos);
unsigned int IIC_poll(struct file* file, poll_table* wait);
irqreturn_t interrupt_handle( int irq, void* dev_id, struct pt_regs* regs );

static void address_map(void)
{
#define GPIO_BASE (0x56000000)
#define IIC_GPECON ( GPIO_BASE + 0x40 )
#define IIC_GPEUP ( GPIO_BASE + 0x48 )
#define IIC_GPFCON ( GPIO_BASE + 0x50 )
#define IIC_GPFUP ( GPIO_BASE + 0x58 )
#define IIC_EXTINT0 ( GPIO_BASE + 0x88 )
#define IIC_BASE (0x54000000)
#define IIC_CON ( IIC_BASE + 0x0 )
#define IIC_STAT ( IIC_BASE + 0x4 )
#define IIC_ADDR ( IIC_BASE + 0x8 )
#define IIC_DS ( IIC_BASE + 0xC )
R_GPECON = ioremap(IIC_GPECON,4);
R_GPEUP = ioremap(IIC_GPEUP ,4);
R_GPFCON = ioremap(IIC_GPFCON,4);
R_GPFUP = ioremap(IIC_GPFUP ,4);
R_EXTINT0 = ioremap(IIC_EXTINT0 ,4);
R_IICCON = ioremap(IIC_CON ,4);
R_IICSTAT = ioremap(IIC_STAT ,4);
R_IICADD = ioremap(IIC_ADDR ,4);
R_IICDS = ioremap(IIC_DS ,4);
}

static void address_unmap(void)
{
iounmap( R_GPECON );
iounmap( R_GPEUP );
iounmap( R_GPFCON );
iounmap( R_GPFUP );
iounmap( R_EXTINT0 );
iounmap( R_IICCON );
iounmap( R_IICSTAT );
iounmap( R_IICADD );
iounmap( R_IICDS );
}

static struct file_operations fops = {
.owner = THIS_MODULE,
.read = IIC_read,
.open = IIC_open,
.release = IIC_release,
.poll = IIC_poll,
};

struct IIC_dev{
wait_queue_head_t rq; // 读取等待队列
uint8_t key; //用于存放键值
struct semaphore sem;
struct cdev cdev;
};
struct IIC_dev *zlg7290_dev;


//*********************[ Delay ]*********************************
void Delay(int times)
{
udelay(1000);
}



//************************[ _Rd2410Iic ]********************************
void _Rd2410Iic(U32 slvAddr,U32 addr,U32 *rdata)
{
PDEBUG("read---->0\n");
_iicMode = SETRDADDR;
_iicPt = 0;
_iicData[0] = (U8)addr;
_iicDataCount = 1;

R_IICDS = slvAddr&0xfe;
R_IICSTAT = 0xf0; //MasTx,Start

//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1)
Run_IicPoll();

_iicMode = RDDATA;
_iicPt = 0;
_iicDataCount = 1;

R_IICDS = slvAddr|0x01;
R_IICSTAT = 0xb0; //Master Rx,Start
R_IICCON = 0xaf; //Resumes IIC operation.
while(_iicDataCount!=-1)
Run_IicPoll();

*rdata = _iicData[1];

}

//**********************[ Run_IicPoll ]*********************************
void Run_IicPoll(void)
{
if(R_IICCON & 0x10) //第183行,第一个错误在这里,好像说是&这个符号有问题
IicPoll();
}

//**********************[IicPoll ]**************************************
void IicPoll(void)
{
U32 iicSt,i;

iicSt = R_IICSTAT;
if(iicSt & 0x8){
PDEBUG("bus arbitration is failed\n");
} //When bus arbitration is failed.
if(iicSt & 0x4){
PDEBUG("matched\n");
} //When a slave address is matched with IICADD
if(iicSt & 0x2){
PDEBUG("slave address 0000000b\n");
} //When a slave address is 0000000b
if(iicSt & 0x1){
PDEBUG("Ack isn't received\n");
} //When ACK isn't received

switch(_iicMode)
{
case POLLACK:
PDEBUG("poll--ACK\n");
_iicStatus = iicSt;
break;

case RDDATA:
PDEBUG("read--ACK\n");
if((_iicDataCount--)==0)
{
_iicData[_iicPt++] = R_IICDS;

R_IICSTAT = 0x90; //Stop MasRx condition
R_IICCON = 0xaf; //Resumes IIC operation.
Delay(1); //Wait until stop condtion is in effect.
//Too long time...
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicPt++] = R_IICDS;
//The last data has to be read with no ack.
if((_iicDataCount)==0)
R_IICCON = 0x2f; //Resumes IIC operation with NOACK.
else
R_IICCON = 0xaf; //Resumes IIC operation with ACK
break;

case SETRDADDR:
PDEBUG("SETRDADDR\n");
if((_iicDataCount--)==0)
{
break; //IIC operation is stopped because of IICCON[4]
}
R_IICDS = _iicData[_iicPt++];
for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
R_IICCON = 0xaf; //resumes IIC operation.
break;

default:
break;
}
}

static U8 Getkey_zlg7290(void)
{
U8 keypress,repeatcount;
static U32 rdata;
keypress=_Rd2410Iic(ZLG7290_SlaveADDR, ZLG7290_Key,&(rdata));//第254行,第二个错误在这里
// repeatcount=_Rd2410Iic(ZLG7290_SlaveADDR, ZLG7290_RepeatCnt,&(rdata));//这个没有用到
return keypress;
}

...全文
340 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kinges 2008-05-05
  • 打赏
  • 举报
回复
我没有看楼主的代码!


对于IIC按键的程序,我以前写过一个~

如果楼主遇到的是编译问题,就不要问了,这个比较基础~

我认为调试IIC这种东西,关键要看芯片的时序,把时序搞清楚,就很容易做出来了!

注意间隔的 时间,我就是时间没有掌握好,浪费了两天的时间~

wilson0913 2008-05-04
  • 打赏
  • 举报
回复
顶起来
wilson0913 2008-04-30
  • 打赏
  • 举报
回复
错误的代码如下:

第183行:

//**********************[ Run_IicPoll ]*********************************
void Run_IicPoll(void)
{
if(R_IICCON & 0x10) //第183行,第一个错误在这里,好像说是&这个符号有问题
IicPoll();
}

//**********************[IicPoll ]**************************************

第2个错误254行:

static U8 Getkey_zlg7290(void)
{
U8 keypress,repeatcount;
static U32 rdata;
keypress=_Rd2410Iic(ZLG7290_SlaveADDR, ZLG7290_Key,&(rdata));//第254行,第二个错误在这里
// repeatcount=_Rd2410Iic(ZLG7290_SlaveADDR, ZLG7290_RepeatCnt,&(rdata));//这个没有用到
return keypress;
}

第3个错误417行:

//*******************底半部中断******************
void Iic_do_work(unsigned long) //第417行,第三个错误在这里
{
int code = -1 ;
code = Getkey_zlg7290();
enable_irq(IRQ_EINT2);//使能中断
if(code>0)
{
zlg7290_dev->key=code;
printk("get key %d\n",zlg7290_dev->key);
flag = 1;
wake_up_interruptible(&(zlg7290_dev->rq));
}

}
wilson0913 2008-04-30
  • 打赏
  • 举报
回复
make后的错误提示如下:

make -C /qt2440/qt2440-kernel/ M=/mnt/hgfs/share/1 modules
make[1]: Entering directory `/qt2440/qt2440-kernel'
CC [M] /mnt/hgfs/share/1/iic_zlg7290.o
/mnt/hgfs/share/1/iic_zlg7290.c: In function `_Rd2410Iic':
/mnt/hgfs/share/1/iic_zlg7290.c:153: warning: implicit declaration of function `PDEBUG'
/mnt/hgfs/share/1/iic_zlg7290.c:159: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:160: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:170: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:171: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:172: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c: In function `Run_IicPoll':
/mnt/hgfs/share/1/iic_zlg7290.c:183: error: invalid operands to binary &
/mnt/hgfs/share/1/iic_zlg7290.c: In function `IicPoll':
/mnt/hgfs/share/1/iic_zlg7290.c:192: warning: assignment makes integer from pointer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:217: warning: assignment makes integer from pointer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:219: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:220: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:226: warning: assignment makes integer from pointer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:229: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:231: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:240: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:242: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c: In function `Getkey_zlg7290':
/mnt/hgfs/share/1/iic_zlg7290.c:254: error: void value not ignored as it ought to be
/mnt/hgfs/share/1/iic_zlg7290.c:252: warning: unused variable `repeatcount'
/mnt/hgfs/share/1/iic_zlg7290.c: In function `IIC_init':
/mnt/hgfs/share/1/iic_zlg7290.c:296: warning: ISO C90 forbids mixed declarations and code
/mnt/hgfs/share/1/iic_zlg7290.c:318: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c:319: warning: assignment makes pointer from integer without a cast
/mnt/hgfs/share/1/iic_zlg7290.c: In function `IIC_open':
/mnt/hgfs/share/1/iic_zlg7290.c:347: warning: ISO C90 forbids mixed declarations and code
/mnt/hgfs/share/1/iic_zlg7290.c: In function `Iic_do_work':
/mnt/hgfs/share/1/iic_zlg7290.c:417: error: parameter name omitted
make[2]: *** [/mnt/hgfs/share/1/iic_zlg7290.o] Error 1
make[1]: *** [_module_/mnt/hgfs/share/1] Error 2
make[1]: Leaving directory `/qt2440/qt2440-kernel'
make: *** [all] Error 2
wilson0913 2008-04-30
  • 打赏
  • 举报
回复
接上:
static int __init IIC_init(void)
{
// 1. 分配主设备号
dev_t devno = MKDEV( major, minor );
int ret = register_chrdev_region( devno, 1, DEVICE );
if( ret < 0 )
{
printk(KERN_DEBUG "register major number failed with %d\n", ret);
return ret;
}
printk(KERN_DEBUG "%s:register major number OK\n",DEVICE);

// 2. 注册设备
zlg7290_dev = kmalloc(sizeof(struct IIC_dev), GFP_KERNEL);
memset( zlg7290_dev, 0, sizeof(struct IIC_dev) );
cdev_init( &zlg7290_dev->cdev, &fops );
zlg7290_dev->cdev.ops = &fops;
zlg7290_dev->cdev.owner = THIS_MODULE;
ret = cdev_add( &zlg7290_dev->cdev, devno, 1 );
if( ret < 0 )
{
printk(KERN_DEBUG "register device failed with %d\n", ret);
return ret;
}
printk(KERN_DEBUG "%s:register device OK\n",DEVICE);

// 3. 初始化信号量
init_MUTEX( &(zlg7290_dev->sem) );
printk(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);

// 4. 初始化等待队列头
init_waitqueue_head(&zlg7290_dev->rq);

// 5. Remap IIC 寄存器
address_map();

//7.初始化中断
U32 tmp = ioread32( R_GPFCON );
tmp |= 0x00000020; //设置GPF2:EINT2
iowrite32( tmp, R_GPECON );

tmp = ioread32( R_GPFUP );
tmp |= 0x04; //Pull-up disable
iowrite32( tmp, R_GPFUP );

tmp = ioread32( R_EXTINT0 );
tmp &= 0x0; //设置EINT2为低电平触发
iowrite32( tmp, R_GPFUP );
// 8. 初始化底半部中断工作队列
INIT_WORK(&Iic_wq,(void(*)(void*))Iic_do_work,NULL);

// 9. 设置 s3c2410 IIC
tmp = ioread32( R_GPEUP );
tmp |= 0xc000; //Pull-up disable
iowrite32( tmp, R_GPEUP );

tmp = ioread32( R_GPECON );
tmp |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL
iowrite32( tmp, R_GPECON );
R_IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
R_IICSTAT = 0X10;
return 0;
}


static void __exit IIC_exit(void)
{
dev_t devno = MKDEV( major, minor );
// 以相反的顺序清除
address_unmap();
cdev_del( &zlg7290_dev->cdev );
kfree( zlg7290_dev );
printk(KERN_DEBUG "%s:kfree OK\n",DEVICE);
unregister_chrdev_region( devno, 1 );
printk(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
}

int IIC_open(struct inode *inode, struct file *file)
{
struct IIC_dev *dev = container_of(inode->i_cdev, struct IIC_dev, cdev);
file->private_data = dev;

if( down_interruptible(&dev->sem) )
return -ERESTARTSYS;

// set_slave_recv_mode();

int ret = request_irq( IRQ_EINT2, interrupt_handle,
SA_INTERRUPT, DEVICE, (void*)dev );
if( ret )
{
printk( KERN_INFO "I2C: can't get assigned irq %d\n", IRQ_IIC );
}
return 0;
}

int IIC_read(struct file *file, char* buf, size_t count, loff_t *f_pos)
{
struct IIC_dev *dev = file->private_data;
int sum=0;
if(flag==1)
{
flag = 0;
sum=1;
if (copy_to_user(buf,&dev->key,1))
{
sum=-EFAULT;
}
}
else
{
if (file->f_flags & O_NONBLOCK)
{
return -EAGAIN;
}
else
{
if(wait_event_interruptible(dev->rq, flag != 0))// 在这里准备睡眠,等待条件为真
{
return - ERESTARTSYS;
}
flag = 0;
sum=1;
if (copy_to_user(buf,&dev->key,1))
{
sum=-EFAULT;
}
}
}
dev->key = 0;
return sum;
}

int IIC_release(struct inode *inode, struct file *file)
{
struct IIC_dev *dev = file->private_data;

iowrite8( 0x0, R_IICCON );
iowrite8( 0x0, R_IICADD );
iowrite8( 0x0, R_IICSTAT);
barrier(); // 强制写入寄存器
free_irq( IRQ_EINT2, interrupt_handle );
up(&dev->sem);
return 0;
}

unsigned int IIC_poll(struct file* file, poll_table* wait)
{
struct IIC_dev *dev = file->private_data;
unsigned int mask = 0;
poll_wait(file, &dev->rq, wait);
if (flag==1)//数据准备好
{
mask |= POLLIN | POLLRDNORM; //设备可无阻塞的读
}
return mask;
}
//*******************底半部中断******************
void Iic_do_work(unsigned long) //第417行,第三个错误在这里
{
int code = -1 ;
code = Getkey_zlg7290();
enable_irq(IRQ_EINT2);//使能中断
if(code>0)
{
zlg7290_dev->key=code;
printk("get key %d\n",zlg7290_dev->key);
flag = 1;
wake_up_interruptible(&(zlg7290_dev->rq));
}

}

//**************顶半部中断***********************
irqreturn_t interrupt_handle( int irq, void* dev_id, struct pt_regs* regs )
{
// struct IIC_dev *dev = dev_id; //一般在共享设备中会用到
disable_irq(IRQ_EINT2);//关中断
schedule_work(&Iic_wq);
return IRQ_HANDLED;
}

module_init(IIC_init);
module_exit(IIC_exit);

MODULE_AUTHOR("panwsecjtu@yhoo.com.cn");
MODULE_DESCRIPTION("Study");
MODULE_SUPPORTED_DEVICE(DEVICE);
MODULE_LICENSE("GPL");


21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧