关于 exynos 4412 按键中断 异步通知
以下是驱动测试代码:
//内核的驱动代码
#include <linux/init.h>
#include <linux/module.h> //for module_init moudule_exit
#include <linux/fs.h> //for MKDEV register_chrdev_region
#include <linux/cdev.h> //字符设备头文件
#include <linux/device.h>
#include <asm/io.h> //for ioremap
#include <linux/platform_device.h> //for 平台设备
#include <linux/of.h>
#include <linux/signal.h>
#include <linux/interrupt.h>
#define LED_MA 500 //主设备号(那一类设备)
//某些主设备号已经静态地分配给了大部分公用设备。见Documentation/devices.txt 。 这里我们常使用250
#define LED_MI 2 //次设备号(这类设备当中的具体哪个设备)
//目标:把字符设备改造为平台设备
//1. 把硬件信息,分离出去,放到设备树
//#define LED3CON 0X11000C20
//#define LED3DAT 0x11000c24
struct resource *led_res_con;
struct resource *led_res_dat;
struct resource *key1_res; //devices source pointer
struct fasync_struct *async_queue; /* 异步结构体指针,用于读 */
struct cdev led; //定义一个字符设备
#define LED_MAGIC 'L' //幻数,类似加密,避免误操作
#define LED_ON _IOW(LED_MAGIC, 1, int)
#define LED_OFF _IOW(LED_MAGIC,2,int)
unsigned int *led3_con;
unsigned int *led3_dat;
int led_open (struct inode *inode, struct file *file)
{
led3_con = ioremap((phys_addr_t)led_res_con,1); //把硬件的物理地址转换为内核的虚拟地址
if(led3_con == NULL){
printk("led3_con ioremap fail\n");
return -1;
}
led3_dat = ioremap((phys_addr_t)led_res_dat,1);
if(led3_dat == NULL){
printk("led3_dat ioremap fail\n");
return -1;
}
writel((readl(led3_con) & (~0xf)) | 1,led3_con);//led3 and key2 had use same register;
writel(1,led3_dat);
printk("led_open ok\n");
return 0;
}
int led_release(struct inode *inode, struct file *file)
{
free_irq(key1_res->start, NULL);
printk("remove OK\n");
printk("led_release ok\n");
return 0;
}
//实现自定义的个性化操作
long led_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{
switch(cmd) //解析ioctl 命令
{
case LED_ON: //点亮灯
printk("led on cmd=%d\n",cmd);
writel(1,led3_dat);
break;
case LED_OFF: //灭灯
printk("led off cmd=%d\n",cmd);
writel(0,led3_dat);
break;
default:
printk("ioctl cmd no found\n");
break;
}
printk("led_ioctl end\n");
return 0;
}
irqreturn_t key_interrupt(int irqno, void *devid)
{
kill_fasync(&async_queue, SIGIO, POLL_IN); //发送SIGIO 异步通知信号
printk("irqno = %d\n", irqno);
return IRQ_HANDLED;
}
int key_fasync (int fd,struct file *filp,int mode)
{
return fasync_helper(fd,filp,mode,&async_queue);//处理标志的变更
}
//3.实现设备的文件操作
struct file_operations fops={ //设备的文件操作
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.unlocked_ioctl = led_ioctl,
.fasync = key_fasync,
};
int led_init(struct platform_device *pdev) //把找到的平台设备的信息传进来
{
int ret;
dev_t dev_id= MKDEV(LED_MA, LED_MI); //把主次设备号合并生成设备ID
//1.注册设备号
ret =register_chrdev_region(dev_id,1,"test_led");
if(ret<0){
printk("regiser led fail\n ");
return -1;
}
//2.初始化字符设备
cdev_init(&led,&fops); //字符设备初始化
ret =cdev_add(&led,dev_id,1); //添加字符设备到系统中
if(ret<0){
printk("cdev add led fail\n ");
return -1;
}
led_res_con = pdev->resource[0].start;
led_res_dat = pdev->resource[1].start;
printk("led init go 1\n");
/*****************************************************/
key1_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (key1_res == NULL) {
printk("No resource !\n");
return -ENODEV;
}
ret = request_irq(key1_res->start, //硬件中断号 对应exynos4412-test4412.dts中test4412-key interrupts = <1 2>中的1
key_interrupt, //中断处理函数
key1_res->flags, //中断标志 IRQF_DISABLED 在表示中断处理时屏蔽掉其它所有中断
"key2", //中断名称 在cat /proc/interrupts 克看到
NULL);
if (ret < 0) {
printk("failed request irq: irqno = irq_res->start");
return ret;
}
printk("key irq init ok\n");
/*********************************************************/
return 0; //返回值为零表示运行成功 ,负值表示失败
}
void led_exit(void)
{
dev_t dev_id= MKDEV(LED_MA, LED_MI);
cdev_del(&led); //删除设备
unregister_chrdev_region(dev_id, 1); //取消注册
printk("led exit go\n");
}
//2.把内核模块的入口,改为platform_driver的入口
//module_init(led_init);
//module_exit(led_exit);
static const struct of_device_id machled[] = {
{ .compatible = "test,led3"}, //必须和设备树里的设备名字一样
{},
};
MODULE_DEVICE_TABLE(of, machled);
struct platform_driver led_platform_driver = {
.driver = {
.name = "test_led",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(machled),
},
.probe = led_init,
.remove = led_exit,
};
module_platform_driver(led_platform_driver); //声明led_platform_driver为平台设备驱动的加载入口
MODULE_LICENSE("Dual BSD/GPL");
接下来是测试代码:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#define LED_MAGIC 'L'
//#define LED_ON 1
//#define LED_OFF 2
#define LED_ON _IOW(LED_MAGIC, 1, int)
#define LED_OFF _IOW(LED_MAGIC,2,int)
int flag = 0;
void input_handler (int signum)
{
printf("receive a signal from globalfifo, signalnum : %d\n",signum);
flag = 1;
}
int main(int argc, char **argv)
{
int fd = open("/dev/led", O_RDWR);
if (fd < 0) {
printf("open /dev/led fail\n");
return -1;
}
int oflags;
signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号
fcntl(fd, F_SETOWN, getpid()); //设置设备文件的所有者为本进程
oflags = fcntl(fd, F_GETFL); // 会调用 驱动中的 .fasync
fcntl(fd, F_SETFL, oflags | FASYNC); //FASYNC 设置支持异步通知模式
while(1)
{
sleep(100);
if (flag)
{
ioctl(fd, LED_OFF); //ioctl 实现设备的个性化操作(可自定义命令)
printf("LED_OFF\n"); //注意要加\n 否则打印信息可能没有
flag = 0;
}
}
}
最后测试下来还是有一些小问题,后续再看;
转载于:https://www.cnblogs.com/fanjuntao/p/11169525.html
关于 exynos 4412 按键中断 异步通知相关推荐
- 按键中断异步通知实现
大体上跟windows的消息处理机制差不多 app所要做的事情 1.绑定信号处理函数 2.通知驱动该程序的pid,好让驱动能够通过pid返回信号 3.设置异步标志位 驱动程序所要做的事情: 1.添加. ...
- Linux 进程间通信 --- 信号通信 --- signal --- signal(SIGINT, my_func); --- 按键驱动异步通知(转)...
信号 ( signal ) 机制是 UNIX 系统中最为古老的进程间通信机制,很多条件可以产生一个信号. 信号的产生: 1,当用户按下某些按键时,产生信号. 2,硬件异常产生信号:除数为 0 ,无效 ...
- linux. qt信号崩溃,【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序+QT捕获Linux系统信号+测试信号通知...
2.驱动程序 安装字符设备驱动程序开发流程开发. 2.1资源定义 定义按键I/O端口号.I/O中断号,以及字符设备的主设备号变量: #define GPIO_KEY1_PIN_NUM (3*32 + ...
- Linux内核中断引入用户空间(异步通知机制)【转】
转自:http://blog.csdn.net/kingdragonfly120/article/details/10858647 版权声明:本文为博主原创文章,未经博主允许不得转载. 当Linux内 ...
- Exynos 4412 看门狗定时器中断
如果想弄懂看门狗定时器中断,要掌握下面两个知识点: 1 懂寄存器 Cortex A9采用的是ARM官方规定的中断处理机制 有两大类寄存器决定了中断工作状态 1) exynos 4412 特有的寄存器( ...
- 字符设备驱动程序之异步通知
如果要实现:平时应用程序处于休眠状态,当按下按键时,驱动告诉应用程序由状态改变,需要读取按键状态了.那么就需要建立驱动和应用程序之间的通信. 应用函数中的某个函数怎么使用,需要包含哪些头文件,可以在服 ...
- liunx驱动----异步通知
查询:消耗资源 中断:read 一直要去读 poll :指定起始时间 异步通知 signal 测试程序 include <stdio.h> include <signal.h> ...
- 异步通知实验(信号)
目录 异步通知 异步通知简介 驱动中的信号处理 应用程序对异步通知的处理 硬件原理图分析 实验程序编写 修改设备树文件 程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 在前面使 ...
- i.MX6ULL终结者Linux异步通知实验编写实验程序
文章目录 1 驱动程序编写 2 应用测试程序 3 运行测试 1 驱动程序编写 本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/13_key_signal 驱动程序在key_po ...
- linux驱动开发学习笔记二十一:异步通知
一.异步通知简介 我们首先来回顾一下"中断",中断是处理器提供的一种异步机制,我们配置好中断以后就可以让处理器去处理其他的事情了,当中断发生以后会触发我们事先设置好的中断服务函数, ...
最新文章
- 厦大计算机研究生和福大,考研:只知道厦门大学?福建还有这些211值得你了解...
- 世界欠他一个图灵奖! LSTM之父的深度学习“奇迹之年”
- Android使用AudioRecord录制pcm音频原始数据以及使用AudioTrack播放
- MIMIC 以太坊医疗项目开发(4)Axios
- vim编写代码时,文件末尾会多一个换行符的解决办法
- 04需求工程软件建模与分析阅读笔记之四
- 蜂鸟智游大数据:“人在囧途”的春运,航空公司们可操碎了心
- linux下编译为知笔记,为知笔记 Linux 版安装
- skynet.fork_Apache Ant 1.10.6发布–用于junitlauncher的fork模式以及新的jmod和链接任务
- 使用Python进行汽车黑客攻击:泄露GPS和OBDIICAN总线数据
- 1.4部署到IIS「深入浅出ASP.NET Core系列」
- 防计算机病毒的重点,计算机病毒防范技术重点措施(1).doc
- RTl8188EUS设置ap模式
- 家用带宽-路由器的选择
- 跨境电商shopee这个平台怎么样?百万shopee卖家笑了,不要再犹豫了
- 有点意思!用Python 一键群发soul消息找对象
- 详解1M宽带下载速度?1M等于多少kb?
- 宝宝培养 IOS APP 上线
- DeFCN debug记录(训练过程),以及对cvpods框架的分析
- springCloud-day04
热门文章
- WCF Data Services查询
- [WM]怎么让应用程序更省电
- 「代码随想录」213.打家劫舍II 【动态规划】力扣详解!
- 「leetcode」108. 构造二叉搜索树【递归】【迭代】详解!
- 2014 找工作总结
- Navicat Premium 15 for Mac(数据库管理工具)支持Big Sur
- My PaintBrush Pro for mac(专业的绘图画板)
- 开发工具Charles for Mac(信息抓取) v4.6.3b1
- 2019校招Android面试题解1.0
- 利用whistle调试移动端页面