• 驱动第一天 之 第一个驱动.LED


    lcled_drv.c
     1 #include <linux/module.h>
     2 #include <linux/kernel.h>
     3 #include <linux/fs.h>
     4 #include <linux/init.h>
     5 #include <linux/delay.h>
     6 #include <asm/uaccess.h>
     7 #include <asm/irq.h>
     8 #include <asm/io.h>
     9 #include <asm/arch/regs-gpio.h>
    10 #include <asm/hardware.h>
    11 
    12 int major;
    13 volatile unsigned long *gpbcon = NULL;
    14 volatile unsigned long *gpbdat = NULL;
    15 
    16 static int lcled_drv_open(struct inode *inode, struct file *file)
    17 {
    18     *gpbcon &= ~((0x3<<(5*2)) | (0x3<<(6*2)) | (0x3<<(7*2)) | (0x3<<(8*2)));
    19     *gpbcon |= ((0x1<<(5*2)) | (0x1<<(6*2)) | (0x1<<(7*2)) | (0x1<<(8*2)));
    20     return 0;
    21 }
    22 
    23 static ssize_t lcled_drv_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
    24 {
    25     int val;
    26     copy_from_user(&val, buf, count);
    27     if(val == 1){
    28         *gpbdat &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
    29     }else{
    30         *gpbdat |= (1<<5) | (1<<6) | (1<<7) | (1<<8);
    31     }
    32     
    33 }
    34 
    35 static struct file_operations lcled_drv_fops = {
    36     .owner = THIS_MODULE,
    37     .open  = lcled_drv_open,
    38     .write = lcled_drv_write,
    39 };
    40 
    41 static int lcled_drv_init(void)
    42 {
    43     major = register_chrdev(0, "lcled_drv", &lcled_drv_fops);
    44     gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16);
    45     gpbdat = gpbcon + 1;
    46 
    47     return 0;
    48 }
    49 
    50 static void lcled_drv_exit(void)
    51 {
    52     unregister_chrdev(major, "lcled_drv");
    53     iounmap(gpbcon);
    54 }
    55 
    56 
    57 
    58 module_init(lcled_drv_init);
    59 module_exit(lcled_drv_exit);
    60 
    61 MODULE_LICENSE("GPL");
    Makefile
     1 KERN_DIR = /home/book/linux-2.6.25.8
     2 
     3 all:
     4     make -C $(KERN_DIR) M=`pwd` modules 
     5 
     6 clean:
     7     make -C $(KERN_DIR) M=`pwd` modules clean
     8     rm -rf modules.order
     9 
    10 obj-m    += lcled_drv.o
    test
     1 #include <stdio.h>
     2 #include <fcntl.h>
     3 
     4 int main(int argc, char **argv)
     5 {
     6     int fd;
     7     int val = 1;
     8     fd = open("/dev/lcled", O_RDWR);
     9     if (fd < 0)
    10     {
    11         printf("can't open!\n");
    12     }
    13     if (argc != 2)
    14     {
    15         printf("Usage :\n");
    16         printf("%s <on|off>\n", argv[0]);
    17         return 0;
    18     }
    19 
    20     if (strcmp(argv[1], "on") == 0)
    21     {
    22         val  = 1;
    23     }
    24     else
    25     {
    26         val = 0;
    27     }
    28     
    29     write(fd, &val, 4);
    30     return 0;
    31 }

    函数原型:
      int (*open)(struct inode *inode, struct file *filp);

      ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

    module_init(lcled_drv_init);
    module_exit(lcled_drv_exit);是用于注册和删除驱动程序

      这个比较简单,网上有很多分析的文章,这里只是作为自己简单的记录,这个驱动是韦东山《嵌入式linux应用开发完全手册》配套光盘里的first_drv精简的。但是未精简之前的代码在编译的时候会有这个问题:用2.6.22.6内核编译可以顺利通过,但用TQ光盘提供的2.6.25.8内核却会报错,要添加一个头文件:

    #include <linux/device.h>,这样就能编译成功了。(就这个昨天倒腾到今天,主要还是方法欠佳,经验教训!!- -!)再续!!!

  • 相关阅读:
    UNIX网络编程——Socket通信原理和实践
    UNIX环境高级编程——单实例的守护进程
    UNIX环境高级编程——初始化一个守护进程
    UNIX环境高级编程——创建孤儿进程
    UNIX环境高级编程——实现uid to name
    CentOS7中使用yum安装Nginx的方法
    centos7配置IP地址
    关于Dubbo的原理以及详细配置
    关于Java大数操作(BigInteger、BigDecimal)
    关于JSON 与 对象 、集合之间的转换
  • 原文地址:https://www.cnblogs.com/lucheng/p/2829266.html
Copyright © 2020-2023  润新知