操作系统:ubuntu 10.04
交叉编译环境:arm-linux-gcc 4.3.2 ,安装位置 /usr/local/arm/4.3.2/
目标板环境 :OK6410-A linux3.0.1
driver_led.c
1. #include <linux/module.h> 2. 3. #include <linux/kernel.h> 4. #include <linux/fs.h> 5. #include <asm/uaccess.h> 6. #include <linux/miscdevice.h> 7. #include <linux/pci.h> 8. #include <mach/map.h> 9. #include <mach/regs-gpio.h> 10. #include <mach/gpio-bank-m.h> 11. #include <plat/gpio-cfg.h> 12. 13. #define LED_MAJOR 240 14. 15. int led_open (struct inode *inode,struct file *filp) 16. 17. { 18. unsigned tmp; 19. tmp = readl(S3C64XX_GPMCON); 20. tmp = (tmp & ~(0x7U<<1))|(0x1U); 21. writel(tmp, S3C64XX_GPMCON); 22. printk("#########open######\n"); 23. return 0; 24. } 25. 26. ssize_t led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) 27. { 28. printk("#########read######\n"); 29. return count; 30. } 31. 32. 33. ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) 34. { 35. char wbuf[10]; 36. unsigned tmp; 37. printk("#########write######\n"); 38. copy_from_user(wbuf,buf,count); 39. switch(wbuf[0]) 40. { 41. case 0: //off 42. tmp = readl(S3C64XX_GPMDAT); 43. tmp |= (0x1U); 44. writel(tmp, S3C64XX_GPMDAT); 45. break; 46. case 1: //on 47. tmp = readl(S3C64XX_GPMDAT); 48. tmp &= ~(0x1U); 49. writel(tmp, S3C64XX_GPMDAT); 50. break; 51. default : 52. break; 53. } 54. return count; 55. } 56. 57. int led_release (struct inode *inode, struct file *filp) 58. { 59. printk("#########release######\n"); 60. return 0; 61. } 62. 63. struct file_operations led_fops ={ 64. .owner = THIS_MODULE, 65. .open = led_open, 66. .read = led_read, 67. .write = led_write, 68. .release = led_release, 69. } ; 70. 71. int __init led_init (void) 72. { int rc; 73. printk ("Test led dev\n"); 74. rc = register_chrdev(LED_MAJOR,"led",&led_fops); 75. if (rc <0) 76. { 77. printk ("register %s char dev error\n","led"); 78. return -1; 79. } 80. printk ("ok!\n"); 81. return 82. } 83. 84. void __exit led_exit (void) 85. { 86. unregister_chrdev(LED_MAJOR,"led"); 87. printk ("module exit\n"); 88. return ; 89. } 90. 91. module_init(led_init); 92. module_exit(led_exit);
Makefile
1. obj-m := driver_led.o 2. KDIR := ~/Desktop/linux-3.0.1 3. all: 4. make -C $(KDIR) M=$(shell pwd) modules 5. install: 6. cp driver_led.ko /tftpboot/ 7. clean: 8. make -C $(KDIR) M=$(shell pwd) clean
test.c
1. #include <stdio.h> 2. #include <sys/types.h> 3. #include <sys/stat.h> 4. #include <fcntl.h> 5. int main (void) 6. { 7. int fd; 8. char buf[10]={0,1} ; 9. fd = open("/dev/my_led",O_RDWR); 10. if (fd < 0) 11. { 12. printf ("Open /dev/my_led file error\n"); 13. return -1; 14. } 15. while(1) 16. { 17. write(fd,&buf[0],1); 18. sleep(1); 19. write(fd,&buf[1],1); 20. sleep(1); 21. } 22. close (fd); 23. return 0; 24. 25. }
源码下#make生成.ko文件
编译测试程序 #arm-linux-gcc test.c -o test 交叉编译器最好放在/usr/local/arm/.. 解压时加上参数-C/即可。
然后加载驱动 #insmod 系统内核和编译出驱动的内核要一致,不然报错invalid format
创建设备#mknod /dev/my_led c 240 0
运行应用程序
./test
观察到闪烁LED灯。