设为首页 加入收藏

TOP

关于 exynos 4412 按键中断 异步通知(一)
2019-07-11 14:11:17 】 浏览:258
Tags:关于 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 = reques

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于STM32F767两路互补SPWM波(HAL.. 下一篇小容量单片机生成pdf文件

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目