• 【Linux 驱动】简单字符设备驱动架构(LED驱动)


    本文基于icool210开发板,内核版本:linux2.6.35;

    驱动代码:

    (1)头文件:led.h

     1 #ifndef __LED_H__
     2 #define __LED_H__
     3 
     4 #define LED_MAGIC 'l'
     5 #define LED_1_ON    _IO(LED_MAGIC, 0)
     6 #define LED_1_OFF   _IO(LED_MAGIC, 1)
     7 #define LED_2_ON    _IO(LED_MAGIC, 3)
     8 #define LED_2_OFF   _IO(LED_MAGIC, 4)
     9 #define LED_3_ON    _IO(LED_MAGIC, 5)
    10 #define LED_3_OFF   _IO(LED_MAGIC, 6)
    11 #define LED_4_ON    _IO(LED_MAGIC, 7)
    12 #define LED_4_OFF   _IO(LED_MAGIC, 8)
    13 #define LED_5_ON    _IO(LED_MAGIC, 9)
    14 #define LED_5_OFF   _IO(LED_MAGIC, 10)
    15 #define LED_6_ON    _IO(LED_MAGIC, 11)
    16 #define LED_6_OFF   _IO(LED_MAGIC, 12)
    17 
    18 #endif

    (2)代码文件:led.c

      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 #include "led.h"
      7 
      8 #define GPBCON  0xE0200040
      9 #define GPBDAT  0xE0200044
     10 #define GPH0CON 0xE0200C00
     11 #define GPH0DAT 0xE0200C04
     12 unsigned int *led_gpb_config;
     13 unsigned int *led_gpb_data;
     14 unsigned int *led_gph0_config;
     15 unsigned int *led_gph0_data;
     16 
     17 struct cdev led_dev;
     18 dev_t devno;
     19 
     20 /****************************************************************************
     21 ** 函数名: led_open
     22 ** 功  能: led设备驱动的操作函数集的open函数
     23 ** 参  数: struct inode *pstInode
     24 **         struct file *pstFile
     25 ** 日  期: 2017年2月22日
     26 ** 作  者: Rookie
     27 *****************************************************************************/
     28 int led_open(struct inode *pstInode, struct file *pstFile)
     29 {
     30     unsigned int uiDataTemp;
     31 
     32     /*
     33     ** 配置LED对应的GPIO为Output
     34     ** LED1 -- GPB0   LED2 -- GPIO2
     35     ** LED3 -- GPB1   LED4 -- GPIO4
     36     */
     37     led_gpb_config = ioremap(GPBCON, 4);
     38     uiDataTemp = readl(led_gpb_config);
     39     uiDataTemp &= 0xFFFF0000;
     40     uiDataTemp |= 0x1111;
     41     writel(uiDataTemp, led_gpb_config);
     42 
     43     /* LED5 -- GPH0_7   LED6 -- GPH0_5 */
     44     led_gph0_config = ioremap(GPH0CON, 4);
     45     uiDataTemp = readl(led_gph0_config);
     46     uiDataTemp &= 0xF0FFFFF;
     47     uiDataTemp |= 0x10100000;
     48     writel(uiDataTemp, led_gph0_config);
     49 
     50     led_gpb_data = ioremap(GPBDAT, 4);
     51     led_gph0_data = ioremap(GPH0DAT, 4);
     52 
     53     return 0;
     54 }
     55 
     56 /****************************************************************************
     57 ** 函数名: led_ioctl
     58 ** 功  能: led设备驱动的操作函数集的ioctl函数
     59 ** 参  数: struct file *pstFile
     60 **         unsigned int uiCmd
     61 **         unsigned long ulArgc
     62 ** 日  期: 2017年2月22日
     63 ** 作  者: Rookie
     64 *****************************************************************************/
     65 long led_ioctl(struct file *pstFile, unsigned int uiCmd, unsigned long ulArgc)
     66 {
     67     unsigned int uiDataTemp;
     68 
     69     switch (uiCmd)
     70     {
     71         case (LED_1_ON):
     72             uiDataTemp = readl(led_gpb_data);
     73             uiDataTemp |= 0x1;
     74             writel(uiDataTemp, led_gpb_data);
     75             printk("led1--on
    ");
     76             break;
     77 
     78         case (LED_1_OFF):
     79             uiDataTemp = readl(led_gpb_data);
     80             uiDataTemp &= 0xFFFFFFFE;
     81             writel(uiDataTemp, led_gpb_data);
     82             printk("led1--off
    ");
     83             break;
     84 
     85         case (LED_2_ON):
     86             uiDataTemp = readl(led_gpb_data);
     87             uiDataTemp |= 0x4;
     88             writel(uiDataTemp, led_gpb_data);
     89             printk("led2--on
    ");
     90             break;
     91 
     92         case (LED_2_OFF):
     93             uiDataTemp = readl(led_gpb_data);
     94             uiDataTemp &= 0xFFFFFFFB;
     95             writel(uiDataTemp, led_gpb_data);
     96             printk("led2--off
    ");
     97             break;
     98 
     99         case (LED_3_ON):
    100             uiDataTemp = readl(led_gpb_data);
    101             uiDataTemp |= 0x2;
    102             writel(uiDataTemp, led_gpb_data);
    103             break;
    104 
    105         case (LED_3_OFF):
    106             uiDataTemp = readl(led_gpb_data);
    107             uiDataTemp &= 0xFFFFFFFD;
    108             writel(uiDataTemp, led_gpb_data);
    109             break;
    110 
    111         case (LED_4_ON):
    112             uiDataTemp = readl(led_gpb_data);
    113             uiDataTemp |= 0x8;
    114             writel(uiDataTemp, led_gpb_data);
    115             break;
    116 
    117         case (LED_4_OFF):
    118             uiDataTemp = readl(led_gpb_data);
    119             uiDataTemp &= 0xFFFFFFF7;
    120             writel(uiDataTemp, led_gpb_data);
    121             break;
    122 
    123         case (LED_5_ON):
    124             uiDataTemp = readl(led_gph0_data);
    125             uiDataTemp |= 0x80;
    126             writel(uiDataTemp, led_gph0_data);
    127             break;
    128 
    129         case (LED_5_OFF):
    130             uiDataTemp = readl(led_gph0_data);
    131             uiDataTemp &= 0xFFFFFF7F;
    132             writel(uiDataTemp, led_gph0_data);
    133             break;
    134 
    135         case (LED_6_ON):
    136             uiDataTemp = readl(led_gph0_data);
    137             uiDataTemp |= 0x20;
    138             writel(uiDataTemp, led_gph0_data);
    139             break;
    140 
    141         case (LED_6_OFF):
    142             uiDataTemp = readl(led_gph0_data);
    143             uiDataTemp &= 0xFFFFFFDF;
    144             writel(uiDataTemp, led_gph0_data);
    145             break;
    146 
    147         default:
    148             return -EINVAL;
    149     }
    150     
    151     return 0;
    152 }
    153 
    154 
    155 static struct file_operations led_ops =
    156 {
    157     .open = led_open,
    158     .unlocked_ioctl = led_ioctl,
    159 };
    160 
    161 /****************************************************************************
    162 ** 函数名: led_init
    163 ** 功  能: led设备驱动初始化函数
    164 ** 参  数: void
    165 ** 日  期: 2017年2月22日
    166 ** 作  者: Rookie
    167 *****************************************************************************/
    168 static int __init led_init(void)
    169 {
    170     cdev_init(&led_dev, &led_ops);
    171 
    172     alloc_chrdev_region(&devno, 0, 1, "my_led");
    173     cdev_add(&led_dev, devno, 1);
    174 
    175     return 0;
    176 }
    177 
    178 /****************************************************************************
    179 ** 函数名: led_exit
    180 ** 功  能: led设备驱动退出函数
    181 ** 参  数: void
    182 ** 日  期: 2017年2月22日
    183 ** 作  者: Rookie
    184 *****************************************************************************/
    185 static void __exit led_exit(void)
    186 {
    187     cdev_del(&led_dev);
    188     unregister_chrdev_region(devno, 1);
    189     
    190     return;
    191 }
    192 
    193 
    194 module_init(led_init);
    195 module_exit(led_exit);
    196 MODULE_LICENSE("GPL");

    (3)Makefile文件

    1 obj-m := led.o
    2 KDIR := /root/wksp/icool210/linux2.6.35-icool210-v1.8
    3 all:
    4     make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
    5 clean:
    6     rm -rf *.ko *.o *.order *symvers

    (4)测试应用程序:app.c

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <sys/ioctl.h>
     6 #include "led.h"
     7 
     8 int main(int argc, const char *argv[])
     9 {
    10     int iFd;
    11     int iLedNum;
    12     int iLedStatus;
    13 
    14     if (argc < 3)
    15     {
    16         printf("Please Enter 3 Para!
    ");
    17         return -1;
    18     }
    19 
    20     iLedNum = atoi(argv[1]);
    21     iLedStatus = atoi(argv[2]);
    22 
    23     iFd = open("/dev/my_led", O_RDWR);
    24 
    25     if (1 == iLedNum)
    26     {
    27         if (1 == iLedStatus)
    28         {
    29             ioctl( iFd, LED_1_ON);
    30         }
    31         else
    32         {
    33             ioctl( iFd, LED_1_OFF);
    34         }
    35     }
    36     else if (2 == iLedNum)
    37     {
    38         if (1 == iLedStatus)
    39         {
    40             ioctl( iFd, LED_2_ON);
    41         }
    42         else
    43         {
    44             ioctl( iFd, LED_2_OFF);
    45         }
    46     }
    47     else if (3 == iLedNum)
    48     {
    49         if (1 == iLedStatus)
    50         {
    51             ioctl( iFd, LED_3_ON);
    52         }
    53         else
    54         {
    55             ioctl( iFd, LED_3_OFF);
    56         }
    57     }
    58     else if (4 == iLedNum)
    59     {
    60         if (1 == iLedStatus)
    61         {
    62             ioctl( iFd, LED_4_ON);
    63         }
    64         else
    65         {
    66             ioctl( iFd, LED_4_OFF);
    67         }
    68     }
    69     else if (5 == iLedNum)
    70     {
    71         if (1 == iLedStatus)
    72         {
    73             ioctl( iFd, LED_5_ON);
    74         }
    75         else
    76         {
    77             ioctl( iFd, LED_5_OFF);
    78         }
    79     }
    80     else if (6 == iLedNum)
    81     {
    82         if (1 == iLedStatus)
    83         {
    84             ioctl( iFd, LED_6_ON);
    85         }
    86         else
    87         {
    88             ioctl( iFd, LED_6_OFF);
    89         }
    90     }
    91 
    92     return 0;
    93 }

    操作方法:

    (1)编译 .ko 文件

       在驱动代码路径直接执行 make

    (2)编译 应用程序

       arm-linux-gcc -static app.c -o app

    (3)记载内核模块

      insmod led.ko

    (4)创建设备节点

     mknod /dev/my_led c 251 0

    (5) 执行应用程序

    ./app 1 1

  • 相关阅读:
    使用vue-lazyload 加载图片遇到的坑
    nvm 配置安装全局nodejs
    原生 ajax 请求
    angular5 引入第三方插件
    ionic3 组件引用报错问题
    有1到10w这个10w个数,去除2个并打乱次序,如何找出那两个数
    判断数据类型
    统计字符串有多少字节
    php
    数组 、 字符串 简单去重
  • 原文地址:https://www.cnblogs.com/jamesharden/p/6431316.html
Copyright © 2020-2023  润新知