1、实验 8-2 键盘中断驱动实验【实验目的】 掌握键盘原理。 熟悉驱动的中断机制。【实验步骤】第一步: 利用 vi 编辑器,编写一个 Keypad.c 驱动代码;1、 增加驱动所需的头文件和变量#include #include #include #include #include #include #include #include MODULE_LICENSE(“GPL“);#define DEVICE_NAME “emdoor_kbd“#define KEYVALUE_HAVE 1#define KEYVALUE_NO 0#define KPC_DIR 1private_data;KBD_
2、RET kbd_ret;while(1)if(kbd-kbd_status=KEYVALUE_HAVE)kbd_ret = kbd-kbd_buff;copy_to_user(buffer, kbd-kbd_status=KEYVALUE_NO;return sizeof(KBD_RET);elseif (filp-f_flags interruptible_sleep_on(if (signal_pending(current)return -ERESTARTSYS;return sizeof(KBD_RET);3、 实现键盘驱动中断服务例程static void Emdoor_isr_kb
3、d(int irq, void *dev_id, struct pt_regs *reg)printk(KERN_EMERG“Emdoor_isr_kbd,Interruptn“);int kpc_value;KBD_DEV * kbd = (KBD_DEV *) dev_id;spin_lock_irq(kpc_value=KPC;if(kpc_valueif(kbd-kbd_buff!=0xFF)switch(kbd-kbd_buff)case 0x0: kbd-kbd_buff=5; break;case 0x1: kbd-kbd_buff=6; break;case 0x2: kbd-
4、kbd_buff=7; break;case 0x5: kbd-kbd_buff=8; break;case 0x10: kbd-kbd_buff=9; break;case 0x11: kbd-kbd_buff=10; break;case 0x12: kbd-kbd_buff=11; break;case 0x15: kbd-kbd_buff=12; break;case 0x20: kbd-kbd_buff=13; break;case 0x21: kbd-kbd_buff=14; break;case 0x22: kbd-kbd_buff=15; break;case 0x25: kb
5、d-kbd_buff=16; break;default: break;kbd-kbd_status=KEYVALUE_HAVE;else if(kpc_valueif(kbd-kbd_buff!=0x0)switch(kbd-kbd_buff)case 0x40: kbd-kbd_buff=1; break;case 0x2: kbd-kbd_buff=2; break;case 0x4: kbd-kbd_buff=3; break;case 0x20: kbd-kbd_buff=4; break;default: break;kbd-kbd_status=KEYVALUE_HAVE;if
6、( fasync )kill_fasync( wake_up_interruptible(spin_unlock_irq(4、 实现键盘驱动设备打开操作函数static int Emdoor_kbd_open(struct inode *inode, struct file *filp)int ret;printk(KERN_EMERG “ Emdoor_kbd_open!n“);KBD_DEV * kbd;kbd =(KBD_DEV *) kmalloc(sizeof(KBD_DEV ), GFP_KERNEL);KPC=KPC_ASACT | (3wq);pxa_gpio_mode(94
7、| GPIO_ALT_FN_1_IN);/KP_DKINpxa_gpio_mode(95 | GPIO_ALT_FN_1_IN);/KP_DKINpxa_gpio_mode(98 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(99 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(100 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(101 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(102 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(103 | GPIO_ALT_FN_2_OUT);
8、/KP_MKOUTpxa_gpio_mode(104 | GPIO_ALT_FN_2_OUT);/KP_MKOUTpxa_gpio_mode(105 | GPIO_ALT_FN_2_OUT);/KP_MKOUTpxa_gpio_mode(108 | GPIO_ALT_FN_2_OUT);/KP_MKOUTkbd-kbd_status=KEYVALUE_NO;filp-private_data=kbd;ret = request_irq(IRQ_KEYPAD, Emdoor_isr_kbd, SA_INTERRUPT, DEVICE_NAME, kbd);if (ret)printk(KERN_
9、EMERG “ Interrupt init=%x!n“,ret);return ret;return 0;5、 实现键盘驱动 select 和 poll 操作函数static unsigned int Emdoor_kbd_poll(struct file *filp,struct poll_table_struct *wait)printk(KERN_EMERG “ Emdoor_kbd_poll!n“);KBD_DEV * kbd=filp-private_data;poll_wait(filp,return (kbd-kbd_status=KEYVALUE_HAVE) ? (POLLI
10、N|POLLRDNORM): 0 ;static int Emdoor_kbd_release(struct inode *inode, struct file *filp)printk(KERN_EMERG “ Emdoor_kbd_release!n“);KBD_DEV * kbd = filp-private_data;KPC=0x0;Emdoor_kbd_fasync(-1, filp, 0);kfree(kbd );free_irq(IRQ_KEYPAD, kbd);return 0;6、 实现键盘驱动非阻塞访问操作函数static int Emdoor_kbd_fasync(int
11、 fd, struct file * file, int mode)return fasync_helper(fd, file, mode, 7、 键盘驱动文件结构体定义static struct file_operations Keypad_fops = open: Emdoor_kbd_open,read: Emdoor_kbd_read,release: Emdoor_kbd_release,poll: Emdoor_kbd_poll,fasync: Emdoor_kbd_fasync,owner: THIS_MODULE,;8、 键盘驱动初始化函数定义static int _init
12、Emdoor_kbd_init(void)printk(KERN_EMERG “ Emdoor_kpd initializedn“);int ret;ret = register_chrdev(62, DEVICE_NAME, if (ret #include #include #include #include #include #include int fd, fd_max;fd_set readfds;void handle();int main(void)fd=-1;long oflags; fd= open(“/dev/emdoor_kbd“,O_RDWR);if(fd0)print
13、f(“Keypad device open success!n“);elseprintf(“Keypad device open fail!n“);return 0;fd_max = fd;signal(SIGIO, fcntl(fd, F_SETOWN, getpid();oflags = fcntl(fd, F_GETFL);fcntl(fd, F_SETFL, oflags | FASYNC);printf(“Please press the keypad:n“);while(1);void handle() char buf=0;FD_ZERO(FD_SET(fd, select(fd
14、_max + 1, if ( FD_ISSET(fd, printf(“Scancode is 0x%08xn“, buf); 第五步: 利用vi编辑器,编写一个用于编译Keypad_test.c的Makefile 文件;其中CC = arm-linux-gcc为交叉编译工具所在的路径位置,INCLUDEDIR = /usr/local/xscalev1/arm-linux/include为头文件所在的路径# Makefile for Keypad test#CC = /opt/xscalev1/bin/arm-linux-gccINCLUDEDIR = /usr/local/xscalev1
15、/arm-linux/includeCFLAGS = -Wall -I. -I$(INCLUDEDIR)TARGET_TEST=Keypad_testOBJ_TEST = $(TARGET_TEST)SOURCE_TEST = $(TARGET_TEST).cALL: $(CC) $(CFLAGS) -o $(OBJ_TEST) $(SOURCE_TEST)clean:rm -rf $(OBJ_TEST)第六步: 运行 make 命令对 Keypad_test.c 源代码进行编译,用 ls 命令查看编译后的结果,利用 file 命令查看 Keypad_test 文件的格式,应为 ARM 格式的
16、ELF 文件。【图 8-2-2】第七步: 在 Linux 操作系统下输入 minicom,配置串口参数,然后打开 EELiod目标平台电源,平台启动后,按 CTRL+A,然后按 Z,启动串口命令界面,按 S 键,选择 zmodem 传输方式;按回车第八步: 选择 PC 平台中驱动模块文件 Keypad.ko 和驱动测试文件 Keypad_test,并按回车键。下载选中的文件,文件下载完毕后按 ESC 键,退出串口传输,返回目标平台界面。第九步: 在目标平台终端利用 mknod 命令建立设备文件节点;并利用 insmod 命令动态加载驱动模块,同时利用 lsmod 命令查看驱动模块的加载情况,【图 8-2-3】第十步: 在目标平台终端运行八段数码驱动测试程序 Keypad_test,然后按目标平台上键盘阵列中的任一按键,在平台终端将显示键盘驱动中断产生情况、select 和 poll 调用以及返回的键值。【图 8-2-4】第十一步: 按 CTRL+c 退出驱动测试程序,在平台终端将显示驱动退出时的调试信息。【图 8-2-5】第十二步: 在目标平台终端利用 rmnod 卸载 Keypad 驱动模块,查看驱动模块的卸载时输出的信息.【图 8-2-6】