代码示例_中断下半部

发布者:幸福之路最新更新时间:2025-02-07 来源: cnblogs关键字:S5PV210  头文件 手机看文章 扫描二维码
随时随地手机看文章

  1 //头文件

  2 #include <linux/init.h>

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include gpio.h>

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 #include

 14 

 15 

 16 #include

 17 #include

 18 #include

 19 #include

 20 #include

 21 

 22 #define BUTTON_iOC_GET_DATA 0x4321

 23 struct mem_data{

 24     char buf[128];

 25 };

 26 

 27 //定义一个按键的数据包

 28 struct button_event{

 29     int code;         //按键的名称---键值:KEY_DOWN

 30     int value;        //按键的状态---按下:1,松开:0

 31 };

 32 

 33 //设计一个描述按键的结构体类型

 34 struct buttons{

 35     char *name;        //名称

 36     unsigned int irqno;        //中断号

 37     int gpio;                //按键对应的gpio口

 38     int code;                //键值

 39     unsigned long flags;    //触发方式

 40 };

 41 

 42 //定义一个数组来保存多个按键的数据

 43 struct buttons buttons_set[] = {

 44     [0] = {

 45         .name = 'key1_up',

 46         .irqno = IRQ_EINT(0),

 47         .gpio = S5PV210_GPH0(0),

 48         .code = KEY_UP,

 49         .flags = IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,

 50     },

 51     [1] = {

 52         .name = 'key2_down',

 53         .irqno = IRQ_EINT(1),

 54         .gpio = S5PV210_GPH0(1),

 55         .code = KEY_DOWN,

 56         .flags = IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,

 57     },

 58     [2] = {

 59         .name = 'key3_left',

 60         .irqno = IRQ_EINT(2),

 61         .gpio = S5PV210_GPH0(2),

 62         .code = KEY_LEFT,

 63         .flags = IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,

 64     },

 65     [3] = {

 66         .name = 'key4_right',

 67         .irqno = IRQ_EINT(3),

 68         .gpio = S5PV210_GPH0(3),

 69         .code = KEY_RIGHT,

 70         .flags = IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,

 71     },

 72 };

 73 

 74 //面向对象编程----设计设备的类型

 75 struct s5pv210_button{

 76     //unsigned int major;

 77     dev_t  devno;

 78     struct class * cls;

 79     struct device * dev;

 80     struct cdev  *cdev;

 81     unsigned int irqno;

 82     struct button_event event;

 83     wait_queue_head_t wq_head;

 84     

 85     int have_data;        //表示当前是否有数据可读,可读--1,不可读--0

 86 

 87     void * virt_mem;

 88     struct tasklet_struct tasklet;

 89 };

 90 struct s5pv210_button *button_dev;

 91 

 92 //中断下半部的处理函数-----该函数会被内核线程执行

 93 void button_irq_tasklet(unsigned long data)

 94 {

 95     printk('--------^_^ %s------------n',__FUNCTION__);

 96 

 97     //此时有数据可读

 98     button_dev->have_data = 1;

 99 

100     //从等待队列中唤醒阻塞的进程

101     wake_up_interruptible(&button_dev->wq_head);

102     

103 }

104 

105 

106 //实现中断处理函数--------当触发中断时会被执行

107 irqreturn_t button_irq_svc(int irqno, void *dev)

108 {

109     int value;

110     struct buttons *p;

111     printk('--------^_^ %s------------n',__FUNCTION__);

112 

113     //获取当前触发中断的按键信息

114     p = (struct buttons *)dev;

115     

116     //获取产生中断的gpio口的值

117     value = gpio_get_value(p->gpio);

118     //判断是按下还是松开

119     if(value){

120         //松开

121         printk('kernel:%s up!n',p->name);

122         button_dev->event.code = p->code;

123         button_dev->event.value = 0;

124     }else{

125         //按下

126         printk('kenel:%s pressed!n',p->name);

127         button_dev->event.code = p->code;

128         button_dev->event.value = 1;

129     }

130 

131     //将tasklet对象加入到内核线程中

132     tasklet_schedule(&button_dev->tasklet);

133     

134     return IRQ_HANDLED;

135 }

136 

137 //实现设备操作接口

138 int button_open(struct inode *inode, struct file *filp)

139 {

140 

141     printk('--------^_^ %s------------n',__FUNCTION__);

142     

143     return 0;

144 }

145 ssize_t button_read(struct file *filp , char __user *buf , size_t size, loff_t *flags)

146 {

147     int ret;

148     printk('--------^_^ %s------------n',__FUNCTION__);

149     //判读open时,有没有设置flags为NONBLOCK

150     if(filp->f_flags & O_NONBLOCK && !button_dev->have_data)

151         return -EAGAIN;

152         

153     //判断此时是否有数据可读

154     wait_event_interruptible(button_dev->wq_head,button_dev->have_data);

155     

156     //将内核数据转换为用户空间数据

157     ret = copy_to_user(buf,&button_dev->event,size);

158     if(ret > 0){

159         printk('copy_to_user error!n');

160         return -EFAULT;

161     }

162 

163     //将数据返回给应用空间后,清空数据包,同时将hava_data置零

164     memset(&button_dev->event,0,sizeof(button_dev->event));

165     button_dev->have_data = 0;

166     return size;

167 }

168 

169 ssize_t button_write(struct file *filp, const char __user *buf, size_t size, loff_t *flags)

170 {

171 

172     printk('--------^_^ %s------------n',__FUNCTION__);

173 

174     return size;

175 }

176 

177 long button_ioctl(struct file *filp, unsigned int cmd , unsigned long args)

178 {

179     void __user *argp;

180     struct mem_data data;

181     int ret;

182     printk('--------^_^ %s------------n',__FUNCTION__);

183     argp = (void __user *)args;

184 

185     switch(cmd){

186         case BUTTON_iOC_GET_DATA:

187                 memset(data.buf,0,sizeof(data.buf));

188                 memcpy(data.buf, button_dev->virt_mem,sizeof(data.buf));

189                 ret = copy_to_user(argp,&data,sizeof(data));

190                 if(ret > 0){

191                     return -EFAULT;

192                 }

193             break;

194         default:

195             printk('unkown cmd!n');

196     }

197     

198     return 0;

199 }

200 

201 int button_mmap(struct file *filp, struct vm_area_struct *vma)

202 {

203     unsigned int addr;

204     printk('--------^_^ %s------------n',__FUNCTION__);

205 

206     //1,获得一块物理内存空间-----将申请的虚拟空间转换为对应的物理空间

207     addr = virt_to_phys(button_dev->virt_mem);    

208 

209     //2,将物理内存映射到虚拟空间---应用空间

210     

211     vma->vm_flags |= VM_IO;

212     vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

213 

214     if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,

215                     PAGE_SIZE, vma->vm_page_prot)) {

216         printk(KERN_ERR '%s: io_remap_pfn_range failedn',__func__);

217         return -EAGAIN;

218     }

219 

220     return 0;

221 }

222 

223 unsigned int button_poll(struct file *filp, struct poll_table_struct *pts)

224 {

225     unsigned int mask = 0;

226     printk('--------^_^ %s------------n',__FUNCTION__);

227 

228     //1,将等待队列头注册到系统中(VFS)

229     poll_wait(filp,&button_dev->wq_head,pts);

[1] [2] [3]
关键字:S5PV210  头文件 引用地址:代码示例_中断下半部

上一篇:代码示例_ioctl
下一篇:代码示例_LCD控制

推荐阅读最新更新时间:2026-03-19 11:02

S5PV210中的定时器
什么是定时器? 定时器是SoC中常见外设 定时器与计数器。计数器是用来计数的(每隔一个固定时间会计一个数),因为计数器的技术时间周期是固定的,因此到了一定时间,只要用计数值乘以技术的时间周期就能得到一个时间段。这个时间段就是我们定的时间(这就是定时器了)。 定时器/计数器作为SoC的外设,主要用来实现定时执行代码功能,定时器相对于SoC来说,就好像闹钟相对于人来说意义一样 定时器有什么用? 定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU回去处理中断并执行定时器中断的isr从而去执行预先设定好的事件。 定时器就好像是CPU的秘书一样,这
[单片机]
S5PV210 uboot中的 MMU代码分析(1)
1:经过上一节的分析,如果采用SECTION虚拟地址映射的话; 程序员只需要做的事情: (1) 建立转换表,Tanslation Table; (2) 将TTB(转换表基地址Tanslation Table Base)写入协处理器CP15的C2寄存器,这里要注意转换表 基地址为16K对齐的(因为4096*32bit=16K)所以TTB的bit0-bit13为0。 (3) 使能MMU,将CP15的C1寄存器0bit写1; (4) 设置域的访问权限;设置C3寄存器; CPU/MMU做的事情: (1) CPU核心看到和用到的只是虚拟地址VA,至于VA如果去对应物理地址PA,CPU核心不理会,MVA是除CPU核心 外的其他部分看到的虚拟地
[单片机]
<font color='red'>S5PV210</font> uboot中的 MMU代码分析(1)
S5PV210 三个Camera Interface/CAMIF/FIMC的区别
S5PV210有三个CAMIF单元,分别为CAMIF0 CAMIF1和CAMIF2。对应着驱动中的fimc0, fimc1, fimc2。在三星datasheet和驱动代码中CAMIF和FIMC(Fully Interactive Mobile Camera)这两个术语基本上可以互换的,后面我们都用FIMC代替CAMIF。这两个术语的称呼有很强的模糊性,尤其刚刚接触三星平台,会觉得这三个接口设备都是用来控制camera,实际上三个接口并不局限于只控制camera。 我们先看下datasheet中定义的CAMIF feature - 输入支持 1. ITU-R BT601/656/709 mode 2. DMA模式 3.
[单片机]
S5PV210 固件烧写 u-boot烧写
首先阅读CW210_CD自带光盘中CW210 开发板使用手册.pdf 使用usb 拨码开关置成usb启动。xx可以是ON或OFF。开发板上面也有丝印提示 usb线接好,串口线接好 使用DNW下载 自带光盘的usb驱动(x210 usb Driver)只适用于XP系统,如果在Windows 7下使用usb下载,只能使用linux dnw代替 配置DNW串口和下载地址,0xd0020010是x210_usb.bin的下载地址 连接串口,显示连接成功 此时,长按开发板复位按键 直到USB连接显示OK 现在可以通过usb发送文件,首先发送x210_usb.bin 修改下载地址,0x23e00000是u-boot.bin的下
[单片机]
<font color='red'>S5PV210</font> 固件烧写 u-boot烧写
S5PV210 点亮Led
GPC1CON, R/W, Address = 0xE020_0080 GPC1DAT, R/W, Address = 0xE020_0084 举例 #define GPC1CON *((volatile unsigned int*)0xE0200080) #define GPC1DAT *((volatile unsigned int*)0xE0200084) *(unsigned int*)GPC1CON &= ~(0xf 12); *(unsigned int*)GPC1CON |= (0x1 12); *(unsigned int*)GPC1DAT &= ~(0x1 3); *(un
[单片机]
<font color='red'>S5PV210</font> 点亮Led
S5PV210根文件系统的制作(一)
一、基本概念 文件管理:数据管理算法 文件系统:管理文件算法的载体 文件系统的功能:管理分区上的数据(增删查改) 文件系统的分类:fat32/ntfs/ext3/ext4/yaffs/jffs/cramfs/..... 文件系统的表现形态:   window--------- 森林   linux------------ 树 ------- 文件目录标准 文件系统与根文件系统:   根文件系统:  系统启动时加载的助文件系统   其他文件系统:  根系统启动后挂载的其他文件系统 二、需要用到的工具 busybox-1.20.2.tar,yaffs2-source,bash-4.0.t
[单片机]
S5PV210 移植无线wifi网卡 MT7601
一、准备工作 1、MT7601驱动下载 点击下载 2、插入usb WiFi 启动开发板linux,lsusb查看usb驱动 Bus 001 Device 003: ID 148f:7601看到的是该驱动的厂家设备信息 3、解压源码到linux下,确认USB的VID和PID,在rtusb_dev_id.c中 USB_DEVICE_ID rtusb_dev_id = { #ifdef RT6570 {USB_DEVICE(0x148f,0x6570)}, /* Ralink 6570 */ #endif /* RT6570 */ {USB_DEVICE(0x148f, 0x7650)}, /* MT7650 */ #ifdef
[单片机]
<font color='red'>S5PV210</font> 移植无线wifi网卡 MT7601
【ARM裸机s5pv210 】程序烧录
1.SD卡刷uboot   准备工作   (1)securcrt(115200,数据流控制全不选)   (2)usb转串口驱动   (3)破坏iNand中的bootloader已从SD2启动   (4)九鼎x210_fusingtool.exe   (5)准备好的uboot.bin   流程   (1)使用x210_fusingtool将uboot.bin刷入SD卡   (2)板子启动方式选择emmc启动   板子启动流程   开机- 读iNand的uboot失败 - 读SD卡uboot成功 - 运行nandflash中的系统 2.用fastboot刷机   准备工作   (1)OTG数据线,禁用数字签名   (2)fastboo
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved