Linux TQ2440驱动HelloWorld
Linux TQ2440驱动HelloWorld
PS: 原理跳过, 程序贴上
======================================
环境
天嵌TQ2440(ARM 9)
Linux 2.6.30.4(TQ2440开发板系统)
Ubuntu 12.04.5 LTS 32bit (VMWare虚拟机系统)
gcc version 4.6.3(虚拟机 ubuntu gcc 版本)
==========================================
代码结构
----first_drvc(文件夹)
----| ---first_drvc.c
----| ---Makefile
----| ---first_drvc_test.c
=========================================
Ps: 代码根据环境做相应的调整 ...
nfs搭建参考: http://www.cnblogs.com/TS-qrt/articles/linux_nfs.html
驱动设备命令参考: http://www.cnblogs.com/TS-qrt/articles/linux_ko.html
挂载&卸载驱动
=========================================
insmod xxx.ko
rmmod xxx
==========================================
1.first_drvc.c(驱动程序)
ps: 创建设备(device)的时候,由于linux版本的不同,创建设备的方法不一样,具体常看 linux2.6.xx.x/include/linux/device.h文件
Linux 2.6.22.6版本是class_device_create, Linux 2.6.30.4版本是device_create(本版本)
/* first driver test chan*/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/device.h> //for create device after init driver static struct class *firstdrvc_class; static struct class_device *firstdrvc_class_dev; static int first_drvc_open(struct inode * inode, struct file *file) { printk("first_drvc_open\n"); return 0; } static ssize_t first_drvc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { printk("first_drvc_wirte\n"); return 0; } static struct file_operations first_drvc_fops = { .owner = THIS_MODULE, .open = first_drvc_open, .write = first_drvc_write, }; int major; static int first_drvc_init(void) { major = register_chrdev(0, "first_drvc", &first_drvc_fops); // talk to kernel //create dev after init driver firstdrvc_class = class_create(THIS_MODULE, "first_drvc"); firstdrvc_class_dev = device_create(firstdrvc_class, NULL, MKDEV(major, 0), NULL, "xyz"); return 0; } static void first_drvc_exit(void) { unregister_chrdev(major, "first_drvc"); // set down // rm dev device_unregister(firstdrvc_class_dev); class_destroy(firstdrvc_class); return 0; } module_init(first_drvc_init); module_exit(first_drvc_exit); MODULE_LICENSE("GPL");
2.Makefile(编译驱动程序)
obj-m:=first_drvc.o CC=arm-linux-gcc KERNELDIR=/opt/EmbedSky/linux-2.6.30.4 PWD:=$(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
3.first_drvc_test.c (测试驱动的程序)
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(int argc, char ** argv) { int fd; int val = 1; fd = open("/dev/xxx", O_RDWR); // "/dev/xyz" if(fd < 0) printf("can't open!\n"); write(fd, &val, 4); return 0; }
ps:编译
arm-linux-gcc -o first_drvc_test first_drvc_test.c
驱动模板:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/device.h> #include <asm/uaccess.h> // copy_from_user #include <asm/io.h> // ioremap static struct class *keydrvc_class; static struct class_device *keydrvc_class_dev; volatile unsigned long *gpbcon = NULL; volatile unsigned long *gpbdat = NULL; static int key_drvc_open(struct inode * inode, struct file *file) { /* *gpfcon &= ~((0x3<<(1*2)) | (0x3<<(4*2)) | (0x3<<(2*2)) | (0x3<<(0*2))); printk("first_drvc_open\n"); */ return 0; } static ssize_t key_drvc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { /* int val; copy_from_user(&val, buf, count); // copy_to_user(); *gpfdat &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8)); */ return 0; } ssize_t key_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { /* unsigned char key_vals[4]; int regval; if (size != sizeof(key_vals)) return -EINVAL; regval = *gpfdat; key_vals[0] = (regval & (1<<1)) ? 1 : 0; key_vals[1] = (regval & (1<<4)) ? 1 : 0; key_vals[2] = (regval & (1<<2)) ? 1 : 0; key_vals[3] = (regval & (1<<0)) ? 1 : 0; copy_to_user(buf, key_vals, sizeof(key_vals)); return sizeof(key_vals); */ return 0; } static struct file_operations key_drvc_fops = { .owner = THIS_MODULE, .open = key_drvc_open, .write = key_drvc_write, .read = key_drvc_read, }; int major; static int key_drvc_init(void) { major = register_chrdev(0, "key_drvc", &key_drvc_fops); // class and device keydrvc_class = class_create(THIS_MODULE, "key_drvc"); keydrvc_class_dev = device_create(keydrvc_class, NULL, MKDEV(major, 0), NULL, "keys"); //gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16); //gpbdat = gpbcon + 1; return 0; } static void key_drvc_exit(void) { unregister_chrdev(major, "key_drvc"); class_device_unregister(keydrvc_class_dev); class_destroy(keydrvc_class); //iounmap(gpbcon); } module_init(key_drvc_init); module_exit(key_drvc_exit); MODULE_LICENSE("GPL")
-------------- THE END ------------------------------
浙公网安备 33010602011771号