• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

驱动开发10/10-林雪阵

武飞扬头像
林某某..
帮助1

终端输入1--->LED1点亮

终端输入2--->LED2点亮

终端输入3--->LED3点亮

终端输入0--->LED熄灭

 chdev.c (底层驱动代码)

  1.  
    #include <linux/init.h>
  2.  
    #include <linux/module.h>
  3.  
    #include <linux/fs.h>
  4.  
    #include <linux/uaccess.h>
  5.  
    //#include "myled.h"
  6.  
    #include <linux/io.h>
  7.  
    #define CNAME "mycdev"
  8.  
     
  9.  
    #define PHY_LED1_MODER 0X50006000
  10.  
    #define PHY_LED1_ODR 0X50006014
  11.  
    #define PHY_LED1_RCC 0x50000A28
  12.  
     
  13.  
    #define PHY_LED2_MODER 0X50007000
  14.  
    #define PHY_LED2_ODR 0X50007014
  15.  
    #define PHY_LED2_RCC 0x50000A28
  16.  
     
  17.  
    #define PHY_LED3_MODER 0X50006000
  18.  
    #define PHY_LED3_ODR 0X50006014
  19.  
    #define PHY_LED3_RCC 0x50000A28
  20.  
     
  21.  
    int major;
  22.  
    char kbuf[128]={}; //定义数组用于存放和用户之间拷贝的数据
  23.  
    unsigned int *vir_moder1;
  24.  
    unsigned int *vir_moder2;
  25.  
    unsigned int *vir_odr1;
  26.  
    unsigned int *vir_odr2;
  27.  
    unsigned int *vir_rcc;
  28.  
     
  29.  
    ssize_t mycdev_read (struct file *file, char __user *ubuf, size_t size, loff_t *loff)
  30.  
    {
  31.  
    //size是用户期待读到的字节长度
  32.  
    int ret;
  33.  
    if(size>sizeof(kbuf))
  34.  
    size=sizeof(kbuf);
  35.  
    ret=copy_to_user(ubuf,kbuf,size);
  36.  
    if(ret)
  37.  
    {
  38.  
    printk("数据从内核向用户拷贝失败\n");
  39.  
    return -EIO;
  40.  
    }
  41.  
     
  42.  
    return size;
  43.  
    }
  44.  
    ssize_t mycdev_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
  45.  
    {
  46.  
    int ret;
  47.  
    if(size > sizeof(kbuf))
  48.  
    size=sizeof(kbuf);
  49.  
    ret=copy_from_user(kbuf,ubuf,size);
  50.  
    if(ret)
  51.  
    {
  52.  
    printk("数据从用户向内核拷贝失败\n");
  53.  
    return -EIO;
  54.  
    }
  55.  
     
  56.  
    if(kbuf[0] == '1')
  57.  
    {
  58.  
    (*vir_odr1) |= (1<<10);
  59.  
    }else if(kbuf[0]== '2')
  60.  
    {
  61.  
    (*vir_odr2) |= (1<<10);
  62.  
    }
  63.  
    else if(kbuf[0] == '3')
  64.  
    {
  65.  
    (*vir_odr1) |= (1<<8);
  66.  
    }
  67.  
    else
  68.  
    {
  69.  
    (*vir_odr1) &= ~(1<<10);
  70.  
    (*vir_odr2) &= ~(1<<10);
  71.  
    (*vir_odr1) &= ~(1<<8);
  72.  
    }
  73.  
    return size;
  74.  
    }
  75.  
    int mycdev_open (struct inode *inode, struct file *file)
  76.  
    {
  77.  
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
  78.  
    return 0;
  79.  
    }
  80.  
    int mycdev_release (struct inode *inode, struct file *file)
  81.  
    {
  82.  
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
  83.  
    return 0;
  84.  
    }
  85.  
     
  86.  
    struct file_operations fops=
  87.  
    {
  88.  
    .open=mycdev_open,
  89.  
    .read=mycdev_read,
  90.  
    .write=mycdev_write,
  91.  
    .release=mycdev_release
  92.  
    };
  93.  
    static int __init demo_init(void)
  94.  
    {
  95.  
     
  96.  
    major=register_chrdev(0,CNAME,&fops);
  97.  
    if(major<0)
  98.  
    {
  99.  
    printk("字符设备驱动注册失败\n");
  100.  
    return major;
  101.  
    }
  102.  
    printk("字符设备驱动注册成功,major=%d\n",major);
  103.  
     
  104.  
    //moder 地址映射
  105.  
    //GPIOE
  106.  
    vir_moder1=ioremap(PHY_LED1_MODER,4);
  107.  
    if(vir_moder1 ==NULL)
  108.  
    {
  109.  
    printk("vir_moder1 映射失败\n");
  110.  
    return -ENOMEM;
  111.  
    }
  112.  
    printk("vir_moder1 映射成功\n");
  113.  
    //GPIOF
  114.  
    vir_moder2=ioremap(PHY_LED2_MODER,4);
  115.  
    if(vir_moder2 ==NULL)
  116.  
    {
  117.  
    printk("vir_moder2 映射失败\n");
  118.  
    return -ENOMEM;
  119.  
    }
  120.  
    printk("vir_moder2 映射成功\n");
  121.  
     
  122.  
    //odr 地址映射
  123.  
    //GPIOE
  124.  
    vir_odr1=ioremap(PHY_LED1_ODR,4);
  125.  
    if(vir_odr1 ==NULL)
  126.  
    {
  127.  
    printk("vir_odr1 映射失败\n");
  128.  
    return -ENOMEM;
  129.  
    }
  130.  
    printk("vir_odr1 映射成功\n");
  131.  
    //GPIOF
  132.  
    vir_odr2=ioremap(PHY_LED2_ODR,4);
  133.  
    if(vir_odr2 ==NULL)
  134.  
    {
  135.  
    printk("vir_odr2 映射失败\n");
  136.  
    return -ENOMEM;
  137.  
    }
  138.  
    printk("vir_odr2 映射成功\n");
  139.  
     
  140.  
    //rcc 地址映射
  141.  
    vir_rcc=ioremap(PHY_LED1_RCC,4);
  142.  
    if(vir_rcc ==NULL)
  143.  
    {
  144.  
    printk("vir_rcc 映射失败\n");
  145.  
    return -ENOMEM;
  146.  
    }
  147.  
    printk("vir_rcc 映射成功\n");
  148.  
     
  149.  
    //LED1 init
  150.  
    (*vir_moder1) &= (~(3<<20));
  151.  
    (*vir_moder1) |= (1<<20);
  152.  
    (*vir_odr1) &= (~(1<<10));
  153.  
    (*vir_rcc) |= (1<<4);
  154.  
     
  155.  
    //LED2 init
  156.  
    (*vir_moder2) &= (~(3<<20));
  157.  
    (*vir_moder2) |= (1<<20);
  158.  
    (*vir_odr2) &= (~(1<<10));
  159.  
    (*vir_rcc) |= (1<<5);
  160.  
     
  161.  
    //LED3 init
  162.  
    (*vir_moder1) &= (~(3<<16));
  163.  
    (*vir_moder1) |= (1<<16);
  164.  
    (*vir_odr1) &= (~(1<<8));
  165.  
     
  166.  
     
  167.  
    return 0;
  168.  
    }
  169.  
    static void __exit demo_exit(void)
  170.  
    {
  171.  
    unregister_chrdev(major,CNAME);
  172.  
     
  173.  
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
  174.  
     
  175.  
    }
  176.  
    //module_init和module_exit是内核提供的宏
  177.  
    //告诉内核驱动的出口函数和出口函数的地址
  178.  
    module_init(demo_init);
  179.  
    module_exit(demo_exit);
  180.  
    //声明遵循GPL开源协议
  181.  
    MODULE_LICENSE("GPL");
学新通

 test.c(应用层测试代码)

  1.  
    #include <stdio.h>
  2.  
    #include <sys/types.h>
  3.  
    #include <sys/stat.h>
  4.  
    #include <fcntl.h>
  5.  
    #include <unistd.h>
  6.  
    #include <stdlib.h>
  7.  
    #include <string.h>
  8.  
     
  9.  
    int main(int argc, char const *argv[])
  10.  
    {
  11.  
    char buf[128]={};
  12.  
    int fd=open("/dev/mycdev",O_RDWR);
  13.  
    if(fd<0)
  14.  
    {
  15.  
    printf("打开设备文件失败");
  16.  
    exit(-1);
  17.  
    }
  18.  
    printf("设备文件打开成功\n");
  19.  
     
  20.  
    //在终端输入
  21.  
    printf("请输入控制命令 1,2,3开灯 0关灯\n");
  22.  
    fgets(buf,sizeof(buf),stdin);
  23.  
    buf[strlen(buf)-1]='\0';
  24.  
    write(fd,buf,sizeof(buf));
  25.  
     
  26.  
    memset(buf,0,sizeof(buf));
  27.  
    read(fd,buf,sizeof(buf));
  28.  
    printf("读取到的数据为:%s\n",buf);
  29.  
     
  30.  
    close(fd);
  31.  
    return 0;
  32.  
    }
学新通

makefile(编译文件)

  1.  
    modname ?= chdev
  2.  
    arch ?= arm
  3.  
    ifeq ($(arch),arm)#arm架构
  4.  
    KERNELDIR := /home/ubuntu/fsmp1a/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61
  5.  
    else
  6.  
    KERNELDIR := /lib/modules/$(shell uname -r)/build
  7.  
    endif
  8.  
    PWD:=$(shell pwd)
  9.  
    KBUILD_EXTRA_SYMBOLS =/home/ubuntu/08_驱动/day1/1/Module.symvers
  10.  
    all:
  11.  
    make -C $(KERNELDIR) M=$(PWD) modules
  12.  
    # make -C $(KERNELDIR)
  13.  
    #进入内核顶层目录下,读取对应的Makefile文件,然后执行make
  14.  
    #M=$(PWD) :指定编译模块的路径为当前驱动路径
  15.  
    #make modules :模块化编译
  16.  
    #进入
  17.  
    clean:
  18.  
    make -C $(KERNELDIR) M=$(PWD) clean
  19.  
     
  20.  
    obj-m:=$(modname).o
学新通

执行make,生成chdev.ko

和arm-linux-gnueabihf-gcc test.c,生成a.out

将两个文件拷贝到 ~/nfs/rootfs 中

在串口工具中安装驱动,并执行a.out,即可驱动LED点亮

 学新通

 执行效果

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhibfggi
系列文章
更多 icon
同类精品
更多 icon
继续加载