/* butt_drv.c */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm-arm/arch-s3c2410/regs-gpio.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm-arm/arch-s3c2410/irqs.h>
#include <asm-arm/irq.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>
#include "butt_drv.h"
static st_key_info_matrix key_info_matrix[MAX_COLUMN][MAX_ROW] =
{
{{10, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11},
{11, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6},
{12, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13},
{16, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2}},
{{7, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11},
{8, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6},
{9, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13},
{15, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2}},
{{4, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11},
{5, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6},
{6, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13},
{14, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2}},
{{1, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11},
{2, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6},
{3, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13},
{13, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2}},
};
static st_key_buffer key_buffer; /* 键盘缓冲区 */
static spinlock_t buffer_lock; /*缓冲区锁 */
static int button_major = 0;
/* 获取当前的毫秒数(从系统启动开始)*/
static unsigned long get_tick_count(void)
{
struct timeval currTick;
unsigned long ulRet;
do_gettimeofday(&currTick);
ulRet = currTick.tv_sec;
ulRet *= 1000;
ulRet += (currTick.tv_usec + 500) / 1000;
return ulRet;
}
/* 初始化键盘缓冲区 */
static void init_keybuffer(void)
{
int i;
spin_lock_irq(&buffer_lock); /* 获得一个自旋锁 */
key_buffer.head = 0;
key_buffer.tail = 0;
for(i = 0; i < MAX_KEY_COUNT; i++)
{
key_buffer.buf[i] = 0;
key_buffer.jiffy[i] = 0;
}
spin_unlock_irq(&buffer_lock); /* 释放自旋锁 */
}
/* 从缓冲删除过时数据(5秒前的按键值) */
static void remove_timeoutkey(void)
{
unsigned long tick;
spin_lock_irq(&buffer_lock); /* 获得一个自旋锁 */
while(key_buffer.head != key_buffer.tail)
{
tick = get_tick_count() - key_buffer.jiffy[key_buffer.head];
if (tick < 5000) /* 5秒 */
break;
key_buffer.buf[key_buffer.head] = 0;
key_buffer.jiffy[key_buffer.head] = 0;
key_buffer.head ++;
key_buffer.head &= (MAX_KEY_COUNT -1);
}
spin_unlock_irq(&buffer_lock); /* 释放自旋锁 */
}
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
unsigned long base = S3C2410_GPIO_BASE(pin);
unsigned long shift = 1;
unsigned long mask = 0x03;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB)
{
shift = 0;
mask = 0x01;
}
mask <<= (S3C2410_GPIO_OFFSET(pin) << shift);
local_irq_save(flags);
con = __raw_readl(base + 0x00);
con &= ~mask;
con |= function;
__raw_writel(con, base + 0x00);
local_irq_restore(flags);
}
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
unsigned long base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offs);
dat |= to << offs;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
}
unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
unsigned long base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long dat = 0;
unsigned long flags;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
local_irq_restore(flags);
return ((dat & (1 << offs)) >> offs);
}
/* 初始化GPIO, 设置中断0, 2, 11, 19为下降沿中断 */
static void init_gpio(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_OUTP); /* GPE11 */
s3c2410_gpio_setpin(S3C2410_GPE11, 0);
s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_OUTP); /* GPE13 */
s3c2410_gpio_setpin(S3C2410_GPE13, 0);
s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_OUTP); /* GPG2 */
s3c2410_gpio_setpin(S3C2410_GPG2, 0);
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_OUTP); /* GPG6 */
s3c2410_gpio_setpin(S3C2410_GPG6, 0);
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); /* GPF0 */
s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2); /* GPF2 */
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11); /* GPG3 */
s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_EINT19); /* GPG11 */
set_irq_type(IRQ_EINT0, IRQT_FALLING);
set_irq_type(IRQ_EINT2, IRQT_FALLING);
set_irq_type(IRQ_EINT11, IRQT_FALLING);
set_irq_type(IRQ_EINT19, IRQT_FALLING);
}
/* 激活中断 */
static __inline void enable_irqs(void)
{
int i;
for (i = 0; i < MAX_COLUMN; i++)
{
enable_irq(key_info_matrix[i][0].irq_no);
}
}
/* 屏蔽中断 */
static __inline void disable_irqs(void)
{
int i;
for (i = 0; i < MAX_COLUMN; i++)
{
disable_irq(key_info_matrix[i][0].irq_no);
}
}
/*
** 进入中断后, 扫描铵键码
** 返回: 按键码(1-16), 0xff表示错误
*/
static __inline unsigned char button_scan(int irq)
{
unsigned char key_id = 0xff;
unsigned char column = 0xff, row = 0xff;
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_INP); /* GPF0 */
s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_INP); /* GPF2 */
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_INP); /* GPG3 */
s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_INP); /* GPG11 */
switch (irq)
{
case IRQ_EINT0: column = 0; break;
case IRQ_EINT2: column = 1; break;
case IRQ_EINT11: column = 2; break;
case IRQ_EINT19: column = 3; break;
}
if (column != 0xff)
{
s3c2410_gpio_setpin(S3C2410_GPE11, 0);
s3c2410_gpio_setpin(S3C2410_GPG6, 1);
s3c2410_gpio_setpin(S3C2410_GPE13, 1);
s3c2410_gpio_setpin(S3C2410_GPG2, 1);
if (!s3c2410_gpio_getpin(key_info_matrix[column][0].irq_gpio_port))
{
key_id = key_info_matrix[column][0].key_id;
return key_id;
}
s3c2410_gpio_setpin(S3C2410_GPE11, 1);
s3c2410_gpio_setpin(S3C2410_GPG6, 0);
s3c2410_gpio_setpin(S3C2410_GPE13, 1);
s3c2410_gpio_setpin(S3C2410_GPG2, 1);
if (!s3c2410_gpio_getpin(key_info_matrix[column][1].irq_gpio_port))
{
key_id = key_info_matrix[column][1].key_id;
return key_id;
}
s3c2410_gpio_setpin(S3C2410_GPE11, 1);
s3c2410_gpio_setpin(S3C2410_GPG6, 1);
s3c2410_gpio_setpin(S3C2410_GPE13, 0);
s3c2410_gpio_setpin(S3C2410_GPG2, 1);
if (!s3c2410_gpio_getpin(key_info_matrix[column][2].irq_gpio_port))
{
key_id = key_info_matrix[column][2].key_id;
return key_id;
}
s3c2410_gpio_setpin(S3C2410_GPE11, 1);
s3c2410_gpio_setpin(S3C2410_GPG6, 1);
s3c2410_gpio_setpin(S3C2410_GPE13, 1);
s3c2410_gpio_setpin(S3C2410_GPG2, 0);
if (!s3c2410_gpio_getpin(key_info_matrix[column][3].irq_gpio_port))
{
key_id = key_info_matrix[column][3].key_id;
return key_id;
}
}
return key_id;
}
/* 中断处理函数,其中irq为中断号 */
static irqreturn_t button_irq(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char ucKey = 0;
disable_irqs();
/* 延迟50毫秒, 屏蔽按键毛刺 */
udelay(50000);
ucKey = button_scan(irq);
if ((ucKey >= 1) && (ucKey <= 16))
{
/* 如果缓冲区已满, 则不添加 */
if (((key_buffer.head + 1) & (MAX_KEY_COUNT - 1)) != key_buffer.tail)
{
spin_lock_irq(&buffer_lock);
key_buffer.buf[key_buffer.tail] = ucKey;
key_buffer.jiffy[key_buffer.tail] = get_tick_count();
key_buffer.tail ++;
key_buffer.tail &= (MAX_KEY_COUNT -1);
spin_unlock_irq(&buffer_lock);
}
}
init_gpio();
enable_irqs();
return IRQ_HANDLED;/* 2.6内核返回值一般是这个宏 */
}
没有合适的资源?快使用搜索试试~ 我知道了~
嵌入式开发实例
共487个文件
c:87个
c~:71个
o:63个
3星 · 超过75%的资源 需积分: 50 73 下载量 136 浏览量
2018-04-20
11:26:03
上传
评论 1
收藏 1.31MB ZIP 举报
温馨提示
嵌入式linux应用程序开发标准教程(第二版) 课堂实例
资源详情
资源评论
资源推荐
收起资源包目录
嵌入式开发实例 (487个子文件)
#Makefile# 302B
#Makefile#~ 301B
output.0 143KB
output.0 135KB
output.0 123KB
traces.0 39KB
traces.0 39KB
traces.0 5KB
output.1 143KB
output.1 142KB
output.1 123KB
traces.1 21KB
traces.1 21KB
traces.1 15KB
output.2 142KB
traces.2 21KB
output.3 142KB
traces.3 39KB
_exit 9KB
libpow.a 2KB
aa 10KB
configure.ac 487B
configure.ac 473B
configure.ac~ 477B
configure.ac~ 466B
alarm_pause 10KB
Makefile.am 63B
Makefile.am 63B
Makefile.am~ 63B
butt_drv.c 12KB
ntp.c 5KB
gpio_drv.c 5KB
uart_api.c 3KB
producer-customer.c 3KB
uart_api.c 3KB
uart_api_1.c 3KB
pipe_select.c 3KB
test_drv.c 3KB
uart_api.c 3KB
uart_api.c 3KB
multiplex_select.c 3KB
graphics.c 3KB
customer.c 2KB
net_select.c 2KB
shmem.c 2KB
com_target.c 2KB
com_host.c 2KB
producer.c 2KB
multiplex_poll.c 2KB
net_fcntl.c 2KB
server.c 2KB
producer.c 2KB
thread_sem.c 2KB
sigset.c 1KB
thread_mutex.c 1KB
test_drv.mod.c 1KB
multi_proc.c 1KB
multi_proc_wrong.c 1KB
pipe.c 1KB
client.c 1KB
thread_attr.c 1KB
client.c 1KB
customer.c 1KB
thread.c 1KB
copy_file-4.c 1KB
butt_test.c 1KB
msgque.c 1KB
copy_file_3.c 1KB
mylock.c 1KB
copy_file.c 1KB
syslog_daemon.c 1KB
copy_file.c 1KB
lock_set.c 1KB
daemon_proc.c 1KB
msgsnd.c 1KB
msgrcv.c 1KB
sem_com.c 1008B
shmem_base.c 976B
fifo_read.c 970B
standard_io.c 969B
sem_fork.c 967B
ai.c 942B
sem_com.c 934B
daemon.c 932B
test.c 926B
gpio_test.c 870B
fifo_write.c 825B
syslogtest.c 810B
datastruct.c 803B
kill_raise.c 790B
waitpid.c 787B
com_writer.c 712B
getaddrinfo.c 683B
com_reader.c 647B
fork.c 638B
sigaction.c 626B
shell.c 540B
geet.c 530B
write_lock.c 496B
read_lock.c 472B
共 487 条
- 1
- 2
- 3
- 4
- 5
good_night_9527
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论2