led驱动程序设计

LED的驱动程序很简单,按照张字符型设备驱动设计方法顺下来即可实现,这里主要讲几个注意事项。
  一、在linux系统中,操作硬件不能够使用物理地址,一定要用虚拟地址。将物理地址转化为虚拟地址的函数如下:
    #define    ioremap(cookie,size)
    其中cookie为要转化的物理地址,size为转化空间的大小,单位为字节。返回值为转化后的虚拟地址。
  二、在执行程序时我们需要顺带输入参数进去,但是是以字符串的形式输入的,不方便操控。所以用atoi函数将字符串转化为整数,函数原型如下:
    int    atoi(const char *nptr);
  三、点亮LED是对设备的控制,而不是读写。即在驱动程序中ioctl函数里相对应的寄存器的虚拟地址写入值即可。向某个地址写入值的函数为writel函数,原型:
    static    inline    void    writel(unsigned int b, volatile void __iomem *addr)
    第一个参数为写入的值,第二个参数是虚拟地址。
  接下来也没什么了,最关键的就是驱动程序模型。要想写出字符设备驱动一定要学好它,特别重要!!

头文件:

 

 1 #include <linux/module.h>

 2 #include <linux/init.h>

 3 #include <linux/cdev.h>

 4 #include <linux/fs.h>

 5 #include <linux/io.h>

 6 

 7 #define LED_MAGIC 'L'

 8 #define LED_OFF _IO(LED_MAGIC,0)

 9 #define LED_1 _IO(LED_MAGIC,1)

10 #define LED_2 _IO(LED_MAGIC,2)

11 #define LED_3 _IO(LED_MAGIC,3)

12 #define LED_4 _IO(LED_MAGIC,4)

13 #define LED_ALL _IO(LED_MAGIC,5)

 

 

 

驱动程序代码:

  

 1 #include "led.h"

 2 

 3 #define GPBCON 0x56000010

 4 #define GPBDAT 0x56000014

 5 

 6 /*控制LED寄存器的物理地址*/

 7 unsigned int *led_config;

 8 unsigned int *led_data;

 9 

10 /*存储设备号*/

11 dev_t devno;

12 

13 /*分配cdev*/

14 struct cdev cdev;

15 

16 int led_open(struct inode *node, struct file *filp)

17 {

18     /*将物理地址转为虚拟地址*/

19     led_config = ioremap(GPBCON,3);

20     led_data = ioremap(GPBDAT,2);

21 

22     /*向某一地址写入值*/

23     writel(0x15400,led_config);

24 

25     return 0;

26 }

27 /*驱动程序里的设备控制函数*/

28 long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

29 {

30     switch(cmd)

31     {

32         case LED_1:

33             writel(0b00011100000,led_data);

34             return 0;

35         case LED_2:

36             writel(0b00101100000,led_data);

37             return 0;

38         case LED_3:

39             writel(0b00110100000,led_data);

40             return 0;

41         case LED_4:

42             writel(0b00111000000,led_data);

43             return 0;

44         case LED_OFF:

45             writel(0b00111100000,led_data);

46             return 0;

47         case LED_ALL:

48             writel(0,led_data);

49             return 0;

50 

51         default:

52             return -EINVAL;

53     }

54 }

55 

56 /*函数映射关系表*/

57 struct file_operations led_fops = 

58 {

59     .open = led_open,

60     .unlocked_ioctl = led_ioctl,

61 };

62 

63 

64 

65 static int led_init()

66 {

67 

68     /*初始化cdev*/

69     cdev_init(&cdev, &led_fops);

70     /*注册cdev*/

71     alloc_chrdev_region(&devno, 0, 1,"myled");                    //动态分配设备号,第四个参数为设备名称

72     cdev_add(&cdev, devno, 1);

73     return 0;

74 }

75 

76 static void led_exit()

77 {

78     /*删除设备*/

79     cdev_del(&cdev);

80     /*释放设备号*/

81     unregister_chrdev_region(devno,1);

82 }

83 

84 MODULE_LICENSE("GPL");

85 module_init(led_init);

86 module_exit(led_exit);

 

 

应用程序代码:

 1 #include <sys/types.h>

 2 #include <sys/stat.h>

 3 #include <fcntl.h>

 4 #include <sys/ioctl.h>

 5 #include <stdio.h>

 6 #include "led.h"

 7 

 8 int main(int argc, char *argv[])

 9 {

10     int fd;

11     int cmd;

12          

13     if (argc <2 )

14     {

15         printf("please enter the second para!\n");

16         return 0;    

17     }

18          

19     cmd = atoi(argv[1]); 

20          

21     fd = open("/dev/myled",O_RDWR);

22     

23     if(cmd == 0)

24         ioctl(fd,LED_OFF);    

25     if(cmd == 1)

26         ioctl(fd,LED_1);

27     if(cmd == 2)

28         ioctl(fd,LED_2);

29     if(cmd == 3)

30         ioctl(fd,LED_3);

31     if(cmd == 4)

32         ioctl(fd,LED_4);

33     if(cmd == 5)

34         ioctl(fd,LED_ALL);

35              

36     return 0;

37 }

 

你可能感兴趣的:(程序设计)