📄 de2_leds.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 rudimentary device driver controlls the red and green LEDs on the DE2 board.It uses major numbers (LEDS_RED_MAJOR / LEDS_GREEN_MAJOR) for both LEDs lines (red and green) to be ableto create a corresponding device file to access the LEDs. In uClinux for NIOS2 the automatic creation ofdevice files is found in the script located at "vendors/Altera/nios2nommu/romfs_list".In uClinux it works with the following command:mknod /dev/leds_red 666 c 240 0TODO:-----* Make just one routine for each device-handler of both LED lines to reduce code size* Assign one major number and different minor numbers for both LED lines* Read support from device? (if hardware is capable of this feature)*////////////////////////////////////////////////////////////////////////////////////////////////////// // 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"// major numbers for identifying the device files#define LEDS_RED_MAJOR 240#define LEDS_GREEN_MAJOR 241// base-adress mapping to device names according to linux-2.6.x/include/nios2_system.h from SOPC builder#define LEDS_RED_BASE na_LEDR#define LEDS_GREEN_BASE na_LEDG// define buffers for the strings sended to userchar leds_red_string[STRING_LEN]="\0";char leds_green_string[STRING_LEN]="\0";char* leds_red_ptr = leds_red_string;char* leds_green_ptr = leds_green_string;// are device files open?int leds_red_is_open = 0;int leds_green_is_open = 0;///////////////////RED LEDS//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Open handler/////////////////////////////////////////////////////////////////////////static int leds_red_open(struct inode *inode, struct file *file){#ifdef DEBUG printk("leds_red_open called\n");#endif if (leds_red_is_open++) { printk("device busy...\n"); return -EBUSY; } try_module_get(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Release/Close handler/////////////////////////////////////////////////////////////////////////static int leds_red_release(struct inode *inode, struct file *file){#ifdef DEBUG printk("leds_red_release called\n");#endif --leds_red_is_open; module_put(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Write handler/////////////////////////////////////////////////////////////////////////static ssize_t leds_red_write(struct file *filp, const char *buff, size_t len, loff_t * off){#ifdef DEBUG printk("leds_red_write called\n"); printk("buffer to copy: %s\n", buff);#endif int not_copied = 0; unsigned long int value = 0; np_pio *pio_leds_red =(np_pio *)(LEDS_RED_BASE); if(len > (STRING_LEN-1)) len = STRING_LEN-1; /* copy data from user into buffer leds_red_string */ ltoa(leds_red_string,value); not_copied = copy_from_user(leds_red_string,buff,len); leds_red_string[len] = '\0';#ifdef DEBUG printk("write to LED: %s\ncopied: %i\nnot_copied: %i\n", leds_red_string, len-not_copied,not_copied);#endif#ifndef TEST outl((unsigned long int)atol(leds_red_string),&pio_leds_red->np_piodata);#endif return len-not_copied;}///////////////////GREEN LEDS//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Open handler/////////////////////////////////////////////////////////////////////////static int leds_green_open(struct inode *inode, struct file *file){#ifdef DEBUG printk("leds_green_open called\n");#endif if (leds_green_is_open++) { printk("device busy...\n"); return -EBUSY; } try_module_get(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Release/Close handler/////////////////////////////////////////////////////////////////////////static int leds_green_release(struct inode *inode, struct file *file){#ifdef DEBUG printk("leds_green_release called\n");#endif --leds_green_is_open; module_put(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Write handler/////////////////////////////////////////////////////////////////////////static ssize_t leds_green_write(struct file *filp, const char *buff, size_t len, loff_t * off){#ifdef DEBUG printk("leds_green_write called\n"); printk("buffer to copy: %s\n", buff);#endif int not_copied = 0; np_pio *pio_leds_green =(np_pio *)(LEDS_GREEN_BASE); if(len > (STRING_LEN-1)) len = STRING_LEN-1; // copy data from user into buffer leds_red_string not_copied = copy_from_user(leds_red_string,buff,len); leds_red_string[len] = '\0';#ifdef DEBUG printk("write to LED: %s\ncopied: %i\nnot_copied: %i\n", leds_red_string, len-not_copied,not_copied);#endif#ifndef TEST // set pins to output outl(-1,&pio_leds_green->np_piodirection); outl((unsigned long int)atol(leds_red_string),&pio_leds_green->np_piodata);#endif return len-not_copied;}// Structure which assigns handler functions to hardware operations (red LEDs)static struct file_operations fops_leds_red = { .write = leds_red_write, .open = leds_red_open, .release = leds_red_release};// Structure which assigns handler functions to hardware operations (green LEDs)static struct file_operations fops_leds_green = { .write = leds_green_write, .open = leds_green_open, .release = leds_green_release};/////////////////////////////////////////////////////////////////////////// Init funktion/////////////////////////////////////////////////////////////////////////static int __init mod_init(void){ np_pio *pio_leds_red = (np_pio *)(LEDS_RED_BASE); np_pio *pio_leds_green = (np_pio *)(LEDS_GREEN_BASE); // reserving memory regions for both PIO ports if(!request_mem_region((unsigned long)LEDS_RED_BASE, sizeof(np_pio), "de2_leds_red")) return -1; if(!request_mem_region((unsigned long)LEDS_GREEN_BASE, sizeof(np_pio), "de2_leds_green")) return -1; // registering both PIO ports as character devices to the kernel if(register_chrdev(LEDS_RED_MAJOR, "de2_leds_red", &fops_leds_red)) { printk("register_chrdev of de2_leds_red failed!\n"); release_mem_region((unsigned long)LEDS_RED_BASE, sizeof(np_pio)); return -EIO; } if(register_chrdev(LEDS_GREEN_MAJOR, "de2_leds_green", &fops_leds_green)) { printk("register_chrdev of de2_leds_green failed!\n"); release_mem_region((unsigned long)LEDS_GREEN_BASE, sizeof(np_pio)); return -EIO; } #ifdef DEBUG printk("de2_leds registered successfully!\n");#ifdef TEST print("TEST mode active, so no I/O interaction is possible!\n");#endif#endif // set both PIO ports as outputs outl(-1, &pio_leds_red->np_piodirection); outl(-1, &pio_leds_green->np_piodirection); return 0;}/////////////////////////////////////////////////////////////////////////// Exit function (will be spared if build-in device driver selected)/////////////////////////////////////////////////////////////////////////static void __exit mod_exit(void){ // unregistering character devices unregister_chrdev(LEDS_RED_MAJOR,"de2_leds_red"); unregister_chrdev(LEDS_GREEN_MAJOR,"de2_leds_green"); // releasing memory regions release_mem_region((unsigned long)LEDS_RED_BASE, sizeof(np_pio)); release_mem_region((unsigned long)LEDS_GREEN_BASE, sizeof(np_pio));}// declaring the init/exit functions of the modulemodule_init( mod_init );module_exit( mod_exit );MODULE_LICENSE("GPL");MODULE_AUTHOR("Philipp Lutz");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -