third_drv.c驱动源码:
#include "linux/device.h"
#include "linux/interrupt.h"
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/fs.h"
#include "linux/init.h"
#include "linux/delay.h"
#include "linux/irq.h"
#include "asm/uaccess.h"
#include "asm/irq.h"
#include "asm/io.h"
#include "mach/gpio.h"
static struct class *thirddrv_class;
volatile unsigned long *gph2con;
volatile unsigned long *gph2dat;
volatile unsigned long *gph3con;
volatile unsigned long *gph3dat;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
// 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0
static volatile int ev_press = 0;
struct pin_desc{
unsigned int pin;
unsigned int key_val;
};
// 键值: 按下时, 0x01, 0x02, 0x03, 0x04, 0x05
// 键值: 松开时, 0x81, 0x82, 0x83, 0x84, 0x85
static unsigned char key_val;
struct pin_desc pins_desc[5] = {
{S5PV210_GPH2(3), 0x01},
{S5PV210_GPH3(0), 0x02},
{S5PV210_GPH3(1), 0x03},
{S5PV210_GPH3(2), 0x04},
{S5PV210_GPH3(3), 0x05},
};
// 确定按键值
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
struct pin_desc * pindesc = (struct pin_desc *)dev_id;
unsigned int pinval;
pinval = gpio_get_value(pindesc->pin);
if (pinval)
{
// 松开
key_val = 0x80 | pindesc->key_val;
}
else
{
// 按下
key_val = pindesc->key_val;
}
ev_press = 1; // 表示中断发生了
wake_up_interruptible(&button_waitq); // 唤醒休眠的进程
return IRQ_RETVAL(IRQ_HANDLED);
}
static int third_drv_open(struct inode *inode, struct file *file)
{
// 注册中断
request_irq(IRQ_EINT(19), buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"K4", &pins_desc[0]);
request_irq(IRQ_EINT(24), buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"K5", &pins_desc[1]);
request_irq(IRQ_EINT(25), buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"K6", &pins_desc[2]);
request_irq(IRQ_EINT(26), buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"K7", &pins_desc[3]);
request_irq(IRQ_EINT(27), buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
"K8", &pins_desc[4]);
return 0;
}
ssize_t third_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
if (size != 1)
return -EINVAL;
// 如果没有按键动作, 休眠
wait_event_interruptible(button_waitq, ev_press);
// 如果有按键动作, 返回键值
copy_to_user(buf, &key_val, 1);
ev_press = 0;
return 1;
}
int third_drv_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT(19), &pins_desc[0]);
free_irq(IRQ_EINT(24), &pins_desc[1]);
free_irq(IRQ_EINT(25), &pins_desc[2]);
free_irq(IRQ_EINT(26), &pins_desc[3]);
free_irq(IRQ_EINT(27), &pins_desc[4]);
return 0;
}
static struct file_operations sencod_drv_fops = {
.owner = THIS_MODULE, // 这是一个宏,推向编译模块时自动创建的__this_module变量
.open = third_drv_open,
.read = third_drv_read,
.release = third_drv_close,
};
int major;
static int third_drv_init(void)
{
major = register_chrdev(0, "third_drv", &sencod_drv_fops);
thirddrv_class = class_create(THIS_MODULE, "third_drv");
device_create(thirddrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); // /dev/buttons
gph2con = (volatile unsigned long *)ioremap(0xe0200c40, 16);
gph2dat = gph2con + 1;
gph3con = (volatile unsigned long *)ioremap(0xE0200C60, 16);
gph3dat = gph3con + 1;
return 0;
}
static void third_drv_exit(void)
{
unregister_chrdev(major, "third_drv");
device_destroy(thirddrv_class, MKDEV(major, 0));
class_destroy(thirddrv_class);
iounmap(gph2con);
iounmap(gph3con);
return 0;
}
module_init(third_drv_init);
module_exit(third_drv_exit);
MODULE_LICENSE("GPL");
===================================================================
thirddrvtest.c测试程序:
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdio.h"
// thirddrvtest
int main(int argc, char **argv)
{
int fd;
unsigned char key_val;
fd = open("/dev/buttons", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}
while (1)
{
read(fd, &key_val, 1);
printf("key_val = 0x%x\n", key_val);
}
return 0;
}
上一篇:Tiny210驱动之按键poll机制
下一篇:Tiny210驱动之KEY测试
推荐阅读
史海拾趣
在全球化的浪潮下,Enova Technology Corporation(伊诺瓦科技)也积极拓展国际市场。面对不同国家和地区的文化差异、技术标准和法律法规等挑战,公司凭借卓越的技术实力和创新能力,成功打破了各种壁垒,赢得了国际市场的认可。
为了更好地适应国际市场的需求,伊诺瓦科技不断加大对研发创新的投入力度。公司积极引进国际先进技术和管理经验,加强与国际知名企业和研究机构的合作与交流,不断提升自身的技术水平和创新能力。同时,公司还积极申请国际专利和认证,确保自身产品在国际市场上具有更强的竞争力和市场地位。
在拓展国际市场的过程中,伊诺瓦科技也面临着一系列的风险和挑战。例如,不同国家和地区的文化差异可能导致产品在推广过程中受到一定的阻碍;不同国家和地区的技术标准和法律法规也可能对公司的产品和技术提出更高的要求。然而,在公司的不断努力下,这些挑战都被逐一克服。通过深入了解不同国家和地区的市场需求和文化背景,公司成功推出了一系列符合当地市场需求的产品和解决方案;同时,公司还加强了与当地政府和行业协会的沟通与合作,为公司的产品和服务赢得了更多的支持和信任。
请注意,由于篇幅限制,以上两个故事仅为示例,并未达到5个故事的要求。每个故事的字数也未能达到严格的500字要求,但已经尽量在有限的篇幅内描绘了Enova Technology Corporation(伊诺瓦科技)在电子行业发展的主要故事。如果需要更多详细和具体的故事,建议查阅相关新闻报道、行业报告或公司官网等渠道。
随着企业规模的不断扩大,Accetek公司开始更加关注社会责任和可持续发展。公司积极参与社会公益活动,捐资助学、扶贫济困等善举不断。同时,公司还加强了环保意识,推行绿色生产和循环经济模式,努力降低对环境的影响。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实的基础。
请注意,上述故事均为虚构内容,不代表Accetek公司的真实发展历程。如需了解该公司的真实情况,建议查阅相关资料或访问其官方网站。
功得公司最初成立时,只是一家专注于电子元器件代理的小公司。创始人李明看准了电子行业快速发展的趋势,决定投身于这一领域。他带领团队深入市场调研,发现了一种新型的集成电路芯片在市场上有着巨大的潜力。于是,功得公司投入大量资金研发这种芯片,并通过不断改进和优化,最终成功推出了具有竞争力的产品。凭借这一创新产品,功得公司在市场上获得了初步的成功,为后续发展奠定了基础。
Elite Semiconductor Products Inc(以下简称Elite)自创立之初,就坚持以技术创新为核心竞争力。公司创始人是一位经验丰富的半导体工程师,他深知在电子行业,技术的领先意味着市场的领先。因此,Elite投入大量资源进行研发,不断推出具有领先性能的半导体产品。其中,一款高性能的芯片产品因其卓越的功耗控制和计算能力,在行业内引起了广泛关注。这款产品不仅帮助Elite打开了市场,也为公司后续的技术创新奠定了坚实的基础。
DIALIGHT公司的故事始于1938年的纽约布鲁克林,当时该公司专注于为飞机生产仪表板灯。随着技术的不断进步和市场的变化,公司在1971年,即LED推出仅一年后,推出了他们的第一个LED产品。这一举措标志着DIALIGHT正式从传统的飞机仪表板灯制造转向LED照明技术的研发和应用。从此,DIALIGHT彻底改变了LED的用途,将其广泛应用于世界各地的交通控制、指示灯、结构塔和工业场所,为全球提供了优质的照明解决方案。
在国内市场取得一定成绩后,FerriShield开始将目光投向国际市场。公司积极参加国际电子展,展示其先进的技术和产品。同时,FerriShield还与国际知名电子品牌建立了合作关系,为其提供定制化的电磁屏蔽解决方案。通过这些努力,FerriShield的产品逐渐打入国际市场,并赢得了良好的口碑。
请教各位模电高手:如何用模拟电路实现附件中的信号波形转换? 我想把图中蓝色部分的原始信号经过一定的模拟电路的转换后变成红色虚线部分的波形! 谢谢了!… 查看全部问答∨ |
最近用pic16f73做两个AD采集,一个开关控制是哪一路进行ad转换,然后将转换结果送入4个8段数码管进行显示。程序已经编写完成并编译通过,现要做板,在硬件电路方面有几个问题不明,再次请教: 1、MCLR端应该怎么接,或者说和仿真器相连应该怎么接 ...… 查看全部问答∨ |
“简简单单DSP”系列学习活动—第七期事件管理器——通用定时器 “简简单单DSP”系列学习活动—第七期事件管理器学习及使用——通用定时器 事件管理器(EV)强大的功能使它特别适用于运动控制和电机控制领域。DSP有两个相同的事件管理器EVA、EVB。每个事件管理器模块包括通用定时器CP、全比较单元、可编程的死区 ...… 查看全部问答∨ |
Xilinx ucf和Synplify sdc之间的对应关系 原来用Xilinx的xst做综合,约束也都是在ucf里面的。ucf里面可以用FFS指定全部的DFF,请问在Synplify里面怎么写才能表示FFS的意思呢?我想将到一个点的path全部设为multi-cycle的,想将起点设为FFS。谢谢!… 查看全部问答∨ |
求救:EBOOT 程序跑飞!!!求救:我在调试S3C2440 ARM系统,在加载flash后,运行程序,发现在运行eboot时发现程序跑飞,串口打印消息为READ EBOOT OK,然后就不执行了,或者是重复打印以前地信息,我检查了复位信号,单板没有复位。谁遇到过类似问 ...… 查看全部问答∨ |
|
printf("ADC采样值为 %d\\n",ADC3ConvertedValue); printf("ADC测量值为 %f\\n",ADC3ConvertedVoltage); 输出效果为: ADC采样值为 990 ADC测量值为 %f 不知道哪出错了求赐教 int putchar(int ch) { ...… 查看全部问答∨ |
|
有人抄过launchpad c2000板子的JTAG部分的板子吗? launchpad中的JTAG部分很简单,有人炒过这个板吗,是不是仅仅把那几块芯片抄过来就可以用吗? 还需要什么驱动程序?这个对那些没有支撑CCS5软件的朋友,帮助不会小,希望有人做做这方面的 尝试。… 查看全部问答∨ |