说明:
1。0×378为LED地址位,已知
2。未使用ioctl方式,用write代替,因为可以使用bash直接调用测试,较方便。
3。init函数进行模块初始化,先通过misc_register 注册设备,然后申请端口,防止有冲突发生。
4。write方式调用时,需要从用户空间获取数据到内核空间,通过get_user实现,用outb写数据到对应端口上
5。删除模块时记得删除注册的设备和释放端口,否则会出错。
源码:
led.c
- #include <linux/delay.h>
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/kernel.h> /* printk() */
- #include <linux/errno.h> /* error codes */
- #include <linux/init.h>
- #include <linux/ioport.h>
- #include <asm/io.h>
- #include <linux/miscdevice.h>
- #include <asm/uaccess.h>
- #define GPIO_ADD 0x378
- static ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
- {
- /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
- printk(KERN_DEBUG "write %p %p %d\n", buf, ppos, count);
- if (count) {
- size_t i;
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf+i))
- return -EFAULT;
- printk(KERN_DEBUG "outb %x\n", c);
- outb(GPIO_ADD, c);
- }
- }
- return count;
- }
- static int led_open(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- static int led_release(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- static struct file_operations led_fops = {
- open: led_open,
- release: led_release,
- write: led_write,
- };
- static struct miscdevice led_dev =
- {
- minor: MISC_DYNAMIC_MINOR,
- name: "led",
- fops: &led_fops,
- };
- static __init int __myinit(void)
- {
- printk(KERN_INFO "led init\n");
- /*initialize GPIO pin*/
- misc_register(&led_dev);
- request_region(GPIO_ADD, 2, "led region");
- return 0;
- }
- static __exit void __myexit(void)
- {
- misc_deregister(&led_dev);
- printk(KERN_INFO "led unload\n");
- release_region(GPIO_ADD,2);
- }
- module_init(__myinit);
- module_exit(__myexit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("YuYii <fin1983@hotmail.com>");
- MODULE_DESCRIPTION("LED driver");
编译:
- ARCH=i386 CROSS_COMPILE=/usr/local/i686-linux/bin/i686-linux- LINUX_SRC=/home/yuyii/linux24/kernel-stuff/install/linux-2.4.31 make
需要Makefile文件
测试:
insmod 安装后,通过bash命令测试LED:
echo -n -e “\x01″ > /dev/misc/led
另外附上一段应用程序来控制led
- //Includes
- #include<stdio.h> //stand input and output libs
- #include<stdlib.h> //stand sys libs
- #include<string.h> //string libs
- #include<unistd.h> //posix libs
- #include<sys/io.h> //io driver libs
- #include<pthread.h> //thead libs for multiple thread application
- unsigned int STOP=0; //sharded variable for terminate triggering the watch dog
- void delay(int i) //delay function for io ports operation taking effect
- {
- int j=0;
- for(j=0;j<i;j++)
- {
- usleep(100000); //here, 100 ms is enough
- }
- }
- int main() //the major function
- {
- int port = 0x378;
- fprintf(stdout,"========================================================================\n");
- fprintf(stdout,"== ==\n");
- fprintf(stdout,"== LNSP4 STATUS LED TEST PROGRAM ==\n");
- fprintf(stdout,"== ==\n");
- fprintf(stdout,"========================================================================\n");
- //call the io ports driver for io ports access
- if(ioperm(port,1,1))
- {
- fprintf(stdout,"Error for port \n");
- exit(1);
- }
- outb(0x01,port);
- delay(2);
- printf(" status led1 off for 5s \n");
- delay(50);
- outb(0x02,port);
- delay(2);
- printf(" status led2 off for 5s \n");
- delay(50);
- outb(0x03,port);
- delay(2);
- printf(" status led1 and led2 off for 5s \n");
- delay(50);
- outb(0x00,port);
- delay(2);
- printf(" status led1 and led2 on \n");
- }
(注:来源于itlives.cn,本人即将被关闭的空间...)
