⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 de2_buttons.c

📁 Altera DE2开发板的LED、LCD、SEG7和按键的linux下的设备驱动程序
💻 C
字号:
/*  	Copyright (C) 2007 Philipp Lutz	This program is free software; you can redistribute it and/or modify	it under the terms of the GNU General Public License as published by	the Free Software Foundation; either version 2 of the License, or 	(at your option) any later version.	This program is distributed in the hope that it will be useful,	but WITHOUT ANY WARRANTY; without even the implied warranty of	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	GNU General Public License for more details.	You should have received a copy of the GNU General Public License	along with this program; if not, write to the Free Software	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/////////////////////////////////////////////////////////////////////////////////////////////////////*Description:------------This device driver reads the button-values of the DE2 board using an interrupt. As soon as the driver isloaded into the kernel (module or build-in) the interrupt is registered and everytime a button was pressedthis chracter device driver reads out the button-values and stores it in kernel-space memory.For a more sophisticated device driver with kernel work-processes and nonblocking read-accesslook at "drivers/char/altera_pio_button.c".It uses the major number (BUTTONS_MAJOR) to be able to create a corresponding device file to access the buttons.In uClinux for NIOS2 the automatic creation of device files is found in the script located at"vendors/Altera/nios2nommu/romfs_list".In uClinux it works with the following command:mknod /dev/buttons 666 c 240 0*////////////////////////////////////////////////////////////////////////////////////////////////////// // Debug defines:// --------------//// uncomment following line to use the kernelmodule without// io (inb / outb) functions, needed for debug purposses on host machine.//#define TEST// enables debug-kernel-messages (viewed directly in the shell or via "dmesg" command)//#define DEBUG///////////////////////////////////////////////////////////////////////////////////////////////////#include "de2_includes.h"#define BUTTONS_MAJOR		244#define BUTTONS_MINOR		0#define BUTTONS_BASE		na_KEY#define BUTTONS_IRQ		na_KEY_irq#define BUTTONS_BUF_SIZE 	100char buttons_string[4] = "0\0";char *buttons_ptr = buttons_string;int buttons_is_open = 0;int *devid = (int*) BUTTONS_BASE;/////////////////////////////////////////////////////////////////////////// Interrupt Service Routine for button device driver/////////////////////////////////////////////////////////////////////////static irqreturn_t button_isr(int irq, void *dev_id, struct pt_regs *regs){	int status = 0;	np_pio* pio_buttons = (np_pio *)BUTTONS_BASE;#ifdef	DEBUG		printk("de2_buttons ISR called!\n");#endif		if (!pio_buttons) 		return IRQ_NONE;#ifndef TEST		// disable interrupts	outl(0, &pio_buttons->np_pioedgecapture);	// clear active interrupts	outl(0, &pio_buttons->np_piointerruptmask);	status = (~inl(&pio_buttons->np_piodata)) & 0xF;#endif	itoa(buttons_string,status);	buttons_ptr = buttons_string;#ifdef DEBUG	printk("button(s) pressed: %i\n",status);#endif#ifndef TEST	// activate interrupts on all pins	outl(-1, &pio_buttons->np_piointerruptmask);#endif	return IRQ_HANDLED;}/////////////////////////////////////////////////////////////////////////// Start function which is executed on init/////////////////////////////////////////////////////////////////////////static int button_start(int *dev_id){	np_pio *pio_buttons = (np_pio *)(BUTTONS_BASE);#ifndef TEST	// set pins to input mode	outl(0, &pio_buttons->np_piodirection);	// clear active interrupts	outl(0, &pio_buttons->np_pioedgecapture);#endif	// register interrupt	if (request_irq(BUTTONS_IRQ, button_isr, SA_INTERRUPT, "de2_buttons", (void *) (dev_id))) {		printk("de2_buttons: unable to register interrupt %d\n", BUTTONS_IRQ); 		return -1;	}#ifdef DEBUG	printk("button IRQ registered successfully!\n");#endif#ifndef TEST	// activate interrupts on all pins	outl(-1, &pio_buttons->np_piointerruptmask);	itoa(buttons_string,0);#endif	return 0;}/////////////////////////////////////////////////////////////////////////// Open handler/////////////////////////////////////////////////////////////////////////static int button_open(struct inode *inode, struct file *filp){#ifdef DEBUG	printk("button_open called\n");#endif	if (buttons_is_open++) {		printk("device busy...\n");		return -EBUSY;	}	buttons_ptr = buttons_string;	// If buttons were not pressed yet, resp. not pressed since the last read	if (*buttons_ptr == 0) {#ifdef	DEBUG		printk("buttons not pressed yet!\n");#endif		itoa(buttons_string,0); 	}		try_module_get(THIS_MODULE);	return 0;}/////////////////////////////////////////////////////////////////////////// Release/Close handler/////////////////////////////////////////////////////////////////////////static int button_release(struct inode *inode, struct file *filp){#ifdef	DEBUG	printk("button_release called\n");#endif	buttons_is_open--;	module_put(THIS_MODULE);	return 0;}/////////////////////////////////////////////////////////////////////////// Read handler/////////////////////////////////////////////////////////////////////////static ssize_t button_read(struct file *filp, char *buffer, size_t length, loff_t * ppos){	// Number of bytes actually written to the buffer	int bytes_read = 0;#ifdef	DEBUG	printk("button_read called\n");#endif	// If we're at the end of the message, return 0 signifying end of file	if (*buttons_ptr == 0)		return 0;	while (length-- && *buttons_ptr) {		/* The buffer is in the user data segment, not the kernel 		segment so "*" assignment won't work.  We have to use 		put_user which copies data from the kernel data segment to		the user data segment. */		put_user(*(buttons_ptr++), buffer++);		bytes_read++;	}#ifdef DEBUG	printk("bytes read: %i\n",bytes_read);#endif	// return count of bytes, sent to user	return bytes_read;}// Structure which assigns handler functions to hardware operationsstatic struct file_operations fops_buttons = {	.read	=	button_read,	.open	=	button_open,	.release=	button_release,};/////////////////////////////////////////////////////////////////////////// Init funktion/////////////////////////////////////////////////////////////////////////static int __init button_init(void){	// reserving memory regions for the PIO port	if(!request_mem_region((unsigned long)BUTTONS_BASE, sizeof(np_pio), "de2_buttons"))		return -1;		// registering PIO port as character device to the kernel	if(register_chrdev(BUTTONS_MAJOR, "de2_buttons", &fops_buttons))	{		printk("register_chrdev of de2_buttons failed!\n");		release_mem_region((unsigned long)BUTTONS_BASE, sizeof(np_pio));		return -EIO;	}#ifdef  DEBUG	printk("de2_buttons device driver successfully loaded!\n");#ifdef	TEST	printk("TEST mode active, so no I/O interaction is possible!\n");#endif#endif 	// we need to register IRQ at init (not recommended in most other cases!)	button_start(devid);	return 0;}/////////////////////////////////////////////////////////////////////////// Exit function (will be spared if build-in device driver selected)/////////////////////////////////////////////////////////////////////////static void __exit button_exit(void){#ifndef TEST	np_pio *pio_buttons = (np_pio *)(BUTTONS_BASE);	// disable interrupts	outl(0, &pio_buttons->np_piointerruptmask);#endif	// unregister interrupt in linux	free_irq(BUTTONS_IRQ, (void *) (devid));	// unregister character device	unregister_chrdev(BUTTONS_MAJOR,"de2_buttons");	// release memory region		release_mem_region((unsigned long)BUTTONS_BASE, sizeof(np_pio));}module_init(button_init);module_exit(button_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Philipp Lutz");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -