自己在QQ2440上编写的驱动不能进入触摸中断中:
代码如下:/*
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-adc.h>
#include <linux/serio.h>
/* debug macros */
#undef DEBUG
#ifdef DEBUG
#define DPRINTK( x... ) printk("s3c2410-ts: " ##x)
#else
#define DPRINTK( x... )
#endif
#define PEN_UP 0
#define PEN_DOWN 1
#define PEN_FLEETING 2
#define MAX_TS_BUF 16 /* how many do we want to buffer */
#undef USE_ASYNC
#define DEVICE_NAME "s3c2410-ts"
#define TSRAW_MINOR 1
static void __iomem *base_addr;
typedef struct {
unsigned short pressure;
unsigned short x;
unsigned short y;
unsigned short pad;
}TS_RET;
typedef struct {
unsigned int penStatus; /* PEN_UP, PEN_DOWN, PEN_SAMPLE */
TS_RET buf[MAX_TS_BUF]; /* protect against overrun */
unsigned int head, tail; /* head and tail for queued events */
wait_queue_head_t wq;
spinlock_t lock;
//struct cdev cdev;
} TS_DEV;
static TS_DEV tsdev;
#define BUF_HEAD (tsdev.buf[tsdev.head])
#define BUF_TAIL (tsdev.buf[tsdev.tail])
#define INCBUF(x,mod) ((++(x)) & ((mod) - 1))
static int tsMajor = 230;
static void (*tsEvent)(void);
//#define HOOK_FOR_DRAG
#ifdef HOOK_FOR_DRAG
#define TS_TIMER_DELAY (HZ/100) /* 10 ms */
static struct timer_list ts_timer;
#endif
#define wait_down_int(x) (iowrite32((((x)<<8) | S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_XY_PST(3)),base_addr+S3C2410_ADCTSC))
#define AUTOPST (iowrite32((S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_AUTO_PST|S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)),base_addr+S3C2410_ADCTSC))
/*待机模式*/
#define TSC_SLEEP (iowrite32((S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)),base_addr+S3C2410_ADCTSC))
/*启动AD转换*/
#define start_adc_x() (iowrite32((S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(49)|S3C2410_ADCCON_STARTMASK),base_addr+S3C2410_ADCCON))
/*关闭TC中断*/
#define disable_ts_adc()(iowrite32(~(S3C2410_ADCCON_READ_START)&(ioread32(base_addr+S3C2410_ADCCON)),base_addr+S3C2410_ADCCON ))
static int adc_state = 0;
static int x, y; /* touch screen coorinates */
static void tsEvent_raw(void)
{
if (tsdev.penStatus == PEN_DOWN) {
BUF_HEAD.x = x;
BUF_HEAD.y = y;
BUF_HEAD.pressure = PEN_DOWN;
#ifdef HOOK_FOR_DRAG
ts_timer.expires = jiffies + TS_TIMER_DELAY;
add_timer(&ts_timer);
#endif
} else {
#ifdef HOOK_FOR_DRAG
del_timer(&ts_timer);
#endif
BUF_HEAD.x = 0;
BUF_HEAD.y = 0;
BUF_HEAD.pressure = PEN_UP;
}
tsdev.head = INCBUF(tsdev.head, MAX_TS_BUF);
wake_up_interruptible(&(tsdev.wq));
#ifdef USE_ASYNC
if (tsdev.aq)
kill_fasync(&(tsdev.aq), SIGIO, POLL_IN);
#endif
}
static int tsRead(TS_RET * ts_ret)
{
spin_lock_irq(&(tsdev.lock));
ts_ret->x = BUF_TAIL.x;
ts_ret->y = BUF_TAIL.y;
ts_ret->pressure = BUF_TAIL.pressure;
tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF);
spin_unlock_irq(&(tsdev.lock));
return sizeof(TS_RET);
}
static ssize_t s3c2410_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
TS_RET ts_ret;
printk(DEVICE_NAME " ts_read\n");
retry:
if (tsdev.head != tsdev.tail) {
int count;
count = tsRead(&ts_ret);
if (count)
copy_to_user(buffer, (char *)&ts_ret, count);
printk(DEVICE_NAME " ts_read11111111111\n");
return count;
} else {
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(&(tsdev.wq));
if (signal_pending(current))
return -ERESTARTSYS;
printk(DEVICE_NAME " ts_read22222222222222\n");
goto retry;
}
return sizeof(TS_RET);
}
#ifdef USE_ASYNC
static int s3c2410_ts_fasync(int fd, struct file *filp, int mode)
{
return fasync_helper(fd, filp, mode, &(tsdev.aq));
}
#endif
static unsigned int s3c2410_ts_poll(struct file *filp, struct poll_table_struct *wait)
{
poll_wait(filp, &(tsdev.wq), wait);
return (tsdev.head == tsdev.tail) ? 0 : (POLLIN | POLLRDNORM);
}
static inline void start_ts_adc(void)
{
adc_state = 0;
AUTOPST;
start_adc_x();
}
static inline void s3c2410_get_XY(void)
{
disable_ts_adc();
y = (ioread32(base_addr+S3C2410_ADCDAT0)& 0x3ff);
x = (ioread32(base_addr+S3C2410_ADCDAT1)& 0x3ff);
tsdev.penStatus = PEN_DOWN;
DPRINTK("PEN DOWN: x: %08d, y: %08d\n", x, y);
wait_down_int(1);
tsEvent();
}
static void s3c2410_isr_adc(int irq, void *dev_id, struct pt_regs *reg)
{
printk(DEVICE_NAME "adc_isr\n");
spin_lock_irq(&(tsdev.lock));
if (tsdev.penStatus == PEN_UP)
s3c2410_get_XY();
#ifdef HOOK_FOR_DRAG
else
s3c2410_get_XY();
#endif
spin_unlock_irq(&(tsdev.lock));
}
static void s3c2410_isr_tc(int irq, void *dev_id, struct pt_regs *reg)
{
printk(DEVICE_NAME "tc_isr\n");
spin_lock_irq(&(tsdev.lock));
if (tsdev.penStatus == PEN_UP) {
start_ts_adc();
} else {
tsdev.penStatus = PEN_UP;
DPRINTK("PEN UP: x: %08d, y: %08d\n", x, y);
wait_down_int(0);
tsEvent();
}
spin_unlock_irq(&(tsdev.lock));
}
#ifdef HOOK_FOR_DRAG
static void ts_timer_handler(unsigned long data)
{
spin_lock_irq(&(tsdev.lock));
if (tsdev.penStatus == PEN_DOWN) {
start_ts_adc();
}
spin_unlock_irq(&(tsdev.lock));
}
#endif
static int s3c2410_ts_open(struct inode *inode, struct file *filp)
{
tsdev.head = tsdev.tail = 0;
tsdev.penStatus = PEN_UP;
#ifdef HOOK_FOR_DRAG
init_timer(&ts_timer);
ts_timer.function = ts_timer_handler;
#endif
tsEvent = tsEvent_raw;
init_waitqueue_head(&(tsdev.wq));
printk(DEVICE_NAME "ts-open\n");
// MOD_INC_USE_COUNT;
return 0;
}
static int s3c2410_ts_release(struct inode *inode, struct file *filp)
{
#ifdef HOOK_FOR_DRAG
del_timer(&ts_timer);
#endif
// MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations s3c2410_fops = {
owner: THIS_MODULE,
open: s3c2410_ts_open,
read: s3c2410_ts_read,
release: s3c2410_ts_release,
#ifdef USE_ASYNC
fasync: s3c2410_ts_fasync,
#endif
poll: s3c2410_ts_poll,
};
void tsEvent_dummy(void) {}
static int __init s3c2410_ts_init(void)
{
int ret;
tsEvent = tsEvent_dummy;
ret = register_chrdev(tsMajor, DEVICE_NAME, &s3c2410_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't get major number\n");
return ret;
}
/* Enable touch interrupt */
ret = request_irq(IRQ_ADC, s3c2410_isr_adc, IRQF_SAMPLE_RANDOM,
DEVICE_NAME, s3c2410_isr_adc);
if (ret) goto adc_failed;
ret = request_irq(IRQ_TC, s3c2410_isr_tc, IRQF_SAMPLE_RANDOM,
DEVICE_NAME, s3c2410_isr_tc);
if (ret) goto tc_failed;
/*虚拟地址*/
base_addr = ioremap(S3C2410_PA_ADC,0x20);
if (base_addr == NULL)
{
printk(KERN_ERR "Failed to remap register block\n");
return -ENOMEM;
}
/* Wait for touch screen interrupts */
wait_down_int(0);
printk(DEVICE_NAME " initialized\n");
return 0;
tc_failed:
free_irq(IRQ_ADC, s3c2410_isr_adc);
adc_failed:
return ret;
}
static void __exit s3c2410_ts_exit(void)
{
unregister_chrdev(tsMajor, DEVICE_NAME);
free_irq(IRQ_ADC, s3c2410_isr_adc);
free_irq(IRQ_TC, s3c2410_isr_tc);
}
module_init(s3c2410_ts_init);
module_exit(s3c2410_ts_exit);
我调试时:module能装载,open函数能进去,read函数也能进去,停止在read中,等待触摸,
但是每次触摸,就没反应了
就是不能进入触摸中断:
static void s3c2410_isr_tc(int irq, void *dev_id, struct pt_regs *reg)
{
printk(DEVICE_NAME "tc_isr\n");
spin_lock_irq(&(tsdev.lock));
if (tsdev.penStatus == PEN_UP) {
start_ts_adc();
} else {
tsdev.penStatus = PEN_UP;
DPRINTK("PEN UP: x: %08d, y: %08d\n", x, y);
wait_down_int(0);
tsEvent();
}
spin_unlock_irq(&(tsdev.lock));
}
中。
请问大大们:
是不是我的注册中断有问题,或者是adc寄存器映射有问题,或者是管脚没设置,2410的adc管脚都要设置下,2440需要吗,??????
哪位大大能帮忙啊