掌握Linux的中断处理机制及中断响应过程,了解按键的工作原理,完成基于嵌入式Linux系统的中断应用程序设计。
一、实验原理和内容
1、实验原理
(1)查看按键的原理图(如图)
(2)由原理图可知,六个按键分别连到了S3C2440芯片的外部中断8/11/13/14/15/19引脚上,要使用中断方式驱动引脚首先必须将中断引脚设置为中断模式,并确定触发方式,然后编写中断处理函数对中断进行处理。
2、实验内容:驱动按键
二、实验设备与软件环境
1、操作系统:Linux虚拟机、Red Hat Enterprise Linux 6.3。
2、硬件平台:FriendlyARM开发板mini2440。
3、软件:SecureCRT 8.1。
4、内核版本:linux 2.6.32.2。
三、实验操作过程
1.编写button驱动代码(分析代码):button.c
(1)在/opt /shiyan目录下创建lesson_button文件夹
①在/opt/shiyan目录下右击鼠标打开终端;
②输入“mkdir lesson_button”,创建一个名为lesson_button的文件夹;
(2)在终端输入“cd lesson_button”命令,进入lesson_button目录下
(3)运行#gedit button.c
(4)编写button.c代码(源代码见附录1)
2. 编译加载模块进内核
(1)拷贝:把/opt /shiyan/lesson_button/目录下的驱动代码button.c拷到/opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/char路径下
(2)修改Makefile文件
修改 /opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/char目录下的Makefile文件,在图5所示的位置(在120行左右)添加obj-m += button.o
(3)编译模块
①返回到内核目录下/opt/FriendlyARM/mini2440/linux-2.6.32.2
②执行命令:make modules
③完成后在/drivers/char生成button.ko
3.编辑编译应用程序(源代码见附录2)
(1)在/opt /shiyan/lesson_button目录下编辑应用程序button_test.c
(2)在/opt /shiyan/lesson_button目录下执行arm-linux-gcc button_test.c -o button_test命令
4.打开secureCRT,接上mini2440开发板,输入“rz”命令添加button.ko和button_test文件
5.把模块加载到内核
(1)执行命令:insmod button.ko
(2)查看是否已经加载进内核,执行命令lsmod
6.创建设备节点
在secureCRT上执行命令:mknod /dev/button_irq c 233 0
7.下载、运行应用测试程序
修改文件权限,使用命令:chmod 777 button_test
在当前目录下执行./button_test
查看现象:按下K5显示irq is 59则实验成功
8.实验完成
四、操作过程中遇到的异常问题与解决方案
异常问题:执行make modules命令之后,出现问题,无法生成.ko文件。
解决方法:在修改Makefile文件内容的时候,所添加的obj-m += button.o命令格式有问题,将其修改过来即可。
异常问题:在secureCRT上输入“rz”命令添加文件失败,出现文件冲突的提示。
解决方法:有冲突说明所添加的目录下有一个相似的文件,我们将自己的文件更改一下命名或者添加到另一个目录即可。
五、总结
通过这次实验,我大致掌握了Linux的中断处理机制及中断响应过程,了解了按键的工作原理,对基于嵌入式Linux系统的中断应用程序设计实现有了初步的认识。
六、附录
附录1
#include <plat/nand.h>
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <mach/regs-gpio.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <mach/gpio-fns.h>
#include<linux/sched.h>
#include<linux/init.h>
#include<asm/io.h>
#include<linux/uaccess.h>
#define BUTTON_MAJOR 233
#define DEVICE_NAME “button_irq”
static irqreturn_t button_irq_handler(int
irq, void *dev_id)
{
//中断处理函数
printk(“irq is %d \n”, irq);
return IRQ_RETVAL(IRQ_HANDLED);
}
static int button_irq_open(struct inode * inode, struct file * file)
{
//申请中断
request_irq(IRQ_EINT(15),button_irq_handler,IRQF_TRIGGER_FALLING,“K5”,1);
}
static int button_irq_close(struct inode * inode, struct file * file)
{
//释放中断
free_irq(IRQ_EINT(15),1);
return 0;
}
static struct file_operations button_irq_fops = {
.owner = THIS_MODULE,
.open = button_irq_open,
.release = button_irq_close,
};
/*
- 执行“insmod button_irq.ko”命令时就会调用这个函数
*/
static int __init button_irq_init(void)
{
int ret;
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operations结构;
* 这样,主设备号就和具体的file_operations结构联系起来了,
* 操作主设备为BUTTON_MAJOR的设备文件时,就会调用button_irq_fops中的相关成员函数
* BUTTON_MAJOR可以设为0,表示由内核自动分配主设备号
*/
ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &button_irq_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
printk(DEVICE_NAME " initialized\n");
return 0;
}
static void __exit button_irq_exit(void)
{
unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
}
module_init(button_irq_init);
module_exit(button_irq_exit);
附录2
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
//打开设备,把引脚设置为中断
fd = open("/dev/button_irq",O_RDONLY);
if(fd<0)
{
printf("Can’t open /dev/button_irq \n ");
exit(1);
}
while(1);
//关闭设备,释放中断
close(fd);
}