第五十一讲 platform

文章目录

  • 第五十一讲 platform
    • 一、前言
    • 二、函数说明
      • 1、platform_bus_init
      • 2、platform_device_register
      • 3、platform_driver_register
      • 4、platform_get_resource
    • 三、platform实验
      • 1、实验代码
        • dev.c
        • drv.c
        • gpio.h
        • Makefile
      • 2、实验步骤
    • 四、其他

一、前言

说几句题外话,因为是跟着视频再看,前面的东西我也是懵懵懂懂。随着后面的一些学习,其实前面差不多就是后面的一些基础。kset是在前面是单独的一讲,在上一章xbus里面又看到熟悉的东西了。前面零碎的东西到这边似乎可以连接起来了。还是收获蛮多的。加油!

上一章xbus里面说了软硬分离,在做实验的时候是不是没有这样的感受?这章也许你就能感受到了。在其他软件设计的时候如果资源足够也可以考虑考虑这种思想。这样对于维护、移植都是很方便的。

二、函数说明

1、platform_bus_init

  • 原型:int __init platform_bus_init(void)
  • 说明:在Linux启动的时候自动调用,注册platform总线,名字为platform,并初始化总线。

2、platform_device_register

  • 原型:int platform_device_register(struct platform_device *pdev)
  • 说明:注册平台设备(硬件,继承device)

3、platform_driver_register

  • 原型:

    #define platform_driver_register(drv) \__platform_driver_register(drv, THIS_MODULE)
    extern int __platform_driver_register(struct platform_driver *,struct module *);
    
  • 说明:注册平台驱动(软件)

4、platform_get_resource

  • 原型:struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num)
  • 说明:平台驱动资源获取

三、platform实验

1、实验代码

dev.c

#include <linux/module.h>
#include "gpio.h"
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
static void ledRelease(struct device *dev);
// #include <lin>
static struct resource gLedResource[] =
{[0] = {.start  = GPIO1_DR,.end    = (GPIO1_DR + REGISTER_LENGTH - 1),.flags  = IORESOURCE_MEM,/*内存地址*/},[1] = {.start  = GPIO1_GDIR,.end    = (GPIO1_GDIR + REGISTER_LENGTH - 1),.flags  = IORESOURCE_MEM,/*内存地址*/},[3] = {.start  = GPIO_MUX_GPIO1_PIN4,.end    = (GPIO_MUX_GPIO1_PIN4 + REGISTER_LENGTH - 1),.flags  = IORESOURCE_MEM,/*内存地址*/},[4] = {.start  = GPIO_CCM_CCGR1,.end    = (GPIO_CCM_CCGR1 + REGISTER_LENGTH - 1),.flags  = IORESOURCE_MEM,/*内存地址*/},[5] = {.start  = GPIO_PAD_GPIO1_PIN4,.end    = (GPIO_PAD_GPIO1_PIN4 + REGISTER_LENGTH - 1),.flags  = IORESOURCE_MEM,/*内存地址*/}
};
static struct platform_device led_pdev =
{/* data */.name = "ledPDev",.id = -1,.dev.release = ledRelease, // 设备释放调用.num_resources = ARRAY_SIZE(gLedResource), // 数组资源大小.resource = gLedResource, // 数组资源地址(记录使用的硬件资源)
};static void ledRelease(struct device *dev)
{printk(KERN_ALERT"led device release\r\n");
}
/*模块入口函数 注册平台设备*/
static __init int ledDeviceInit(void)
{printk(KERN_ALERT"led device init\r\n");platform_device_register(&led_pdev);return 0;
}
/*模块退出函数,注销平台设备*/
static __exit void ledDeviceExit(void)
{printk(KERN_ALERT"led device exit\r\n");platform_device_unregister(&led_pdev);
}
module_init(ledDeviceInit);
module_exit(ledDeviceExit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("led module!");
MODULE_ALIAS("led_module");

drv.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>#include <linux/fs.h>
#include <linux/uaccess.h>
#include <asm/io.h>#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/device.h>
static void __iomem *gGpioDr;
static void __iomem *gGpioGdir;
static void __iomem *gGpioMux;
static void __iomem *gGpioCcgr;
static void __iomem *gGpioPad;
static int ledOpen(struct inode *inode, struct file *filp)
{return 0;
}
static ssize_t ledWrite(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{unsigned char writeBuf[10];if(count > 10){return -1;}printk("<1>""led write!");/*将数据从用户空间拷贝到内核空间可以防止传入非法地址导致内核崩溃*/if(copy_from_user(writeBuf, buf, count)){printk("<1> Copy failed!");return -1;}printk("<1> Copy success!");if(!memcmp(writeBuf, "on", 2)){printk("<1>""on!");iowrite32(0 << 4, gGpioGdir);}else{printk("<1>""off!");iowrite32(1 << 4, gGpioGdir);}return count;
}static struct file_operations ledFOps =
{/*THIS_MODULE,它的定义如下是#define THIS_MODULE (&__this_module),__this_module是一个struct module变量,代表当前模块*/.owner = THIS_MODULE,.open = ledOpen,//   .read = ledRead,.write = ledWrite,
};
static struct class *ledClass;
static int ledMajor;
static int ledProbe(struct platform_device *pdev)
{struct resource *mem_dr;struct resource *mem_gdir;struct resource *mem_mux;struct resource *mem_ccgr;struct resource *mem_pad;printk(KERN_ALERT"led probe\r\n");mem_dr      = platform_get_resource(pdev, IORESOURCE_MEM, 0);mem_gdir    = platform_get_resource(pdev, IORESOURCE_MEM, 1);mem_mux     = platform_get_resource(pdev, IORESOURCE_MEM, 2);mem_ccgr    = platform_get_resource(pdev, IORESOURCE_MEM, 3);mem_pad     = platform_get_resource(pdev, IORESOURCE_MEM, 4);gGpioDr     = ioremap(mem_dr->start, resource_size(mem_dr));gGpioGdir   = ioremap(mem_gdir->start, resource_size(mem_gdir));gGpioMux    = ioremap(mem_mux->start, resource_size(mem_mux));gGpioCcgr   = ioremap(mem_ccgr->start, resource_size(mem_ccgr));gGpioPad    = ioremap(mem_pad->start, resource_size(mem_pad));/*使能 gpio 时钟(为了方便全部使能)*/iowrite32(0xffffffff, gGpioCcgr);/*将 gpio 设置为普通 io*/iowrite32(0x05, gGpioMux);/*设置 gpio 属性*/iowrite32(0x10b0, gGpioPad);/*设置 gpio 为输出*/iowrite32(1 << 4, gGpioDr);/*关闭 led 灯*/iowrite32(1 << 4, gGpioGdir);/*创建新的字符设备*/ledMajor = register_chrdev(0, "led_dev", &ledFOps);printk("<1>Major is %d", ledMajor);/*创建class*/ledClass = class_create(THIS_MODULE, "class_led_dev");/*在class下添加kobject对象*/device_create(ledClass, NULL, MKDEV(ledMajor, 0), NULL, "device_led_dev");return 0;
}
static int ledRemove(struct platform_device *dev)
{iounmap(gGpioCcgr);iounmap(gGpioPad);iounmap(gGpioMux);iounmap(gGpioDr);iounmap(gGpioGdir);unregister_chrdev(ledMajor, "led_dev");device_destroy(ledClass, MKDEV(ledMajor, 0));class_destroy(ledClass);return 0;
}
static struct platform_device_id ledIds[] = {{.name = "ledPDev"},{}
};
static struct platform_driver led_pdrv =
{/* data */.driver.name    = "ledPDev",.probe          = ledProbe,.remove         = ledRemove,.id_table       = ledIds,
};static __init int ledDriverInit(void)
{printk(KERN_ALERT"led driver init\r\n");return platform_driver_register(&led_pdrv);
}
static __exit void ledDriverExit(void)
{printk(KERN_ALERT"led driver exit\r\n");platform_driver_unregister(&led_pdrv);
}
module_init(ledDriverInit);
module_exit(ledDriverExit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("ledDrvModule!");
MODULE_ALIAS("ledDrvModule");

gpio.h

#define GPIO1_DR                0x209c004
#define GPIO1_GDIR              0x209c000
#define GPIO_PAD_GPIO1_PIN4     0x20e02f8
#define GPIO_MUX_GPIO1_PIN4     0x20e006c
#define GPIO_CCM_CCGR1          0x20c406c
#define REGISTER_LENGTH         4

Makefile

KERNEL_DIR=../../ebf_linux_kernel/build_image/build/ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
export  ARCH  CROSS_COMPILEobj-m := dev.o drv.oall:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules.PHONE:clean copyclean:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean copy:sudo  cp  *.ko  /home/dragon/nfsshare

2、实验步骤

  1. 编译代码

    make

  2. 将代码复制到共享文件夹

    make copy

  3. 开发板nfs连接共享文件夹

    sudo mount -t nfs 192.168.3.41:/home/dragon/nfsshare /mnt

  4. 加载dev模块

    sudo insmod /mnt/dev.ko

    [14645.331571] dev: loading out-of-tree module taints kernel.
    [14645.349398] led device init
    
  5. 加载drv

    sudo insmod /mnt/drv.ko

    [14714.460540] led driver init
    [14714.471573] led probe
    
  6. 查看注册设备

    ls /dev

  1. 控制led

    打开led

    sudo sh -c "echo 'on'>/dev/device_led_dev"

    [14714.477632] <1>Major is 244
    [15279.036021] <1>led write!
    [15279.038850] <1> Copy success!
    

    关闭led

    sudo sh -c "echo 'off'>/dev/device_led_dev"

    [15279.041476] <1>on!
    [15287.955090] <1>led write!
    [15287.957648] <1> Copy success!
    

四、其他

前面停止了很多天,主要是因为工作上的事情。很抱歉这么久没有更新,前面有小伙伴催我更新,但是还是一直没能来得及。到这里,也提醒一下,估计很多人都发现了,这样学下去还是达不到工作需要,甚至面试都有可能被问懵逼,所以课下要补补课程里面没有的呀。官方的文档也可以好好看看。最后如果可以,代码这些我会找时间统一上传到仓库里面管理。感谢支持呀。

第五十一讲 platform相关推荐

  1. 线性代数学习笔记——第五十一讲——n维向量空间的基、维数与坐标

    1. n维向量空间的一些基本概念(基.维数.标准基) 2. 任一向量在给定基下的坐标是唯一的

  2. 高等数学学习笔记——第五十一讲——高阶线性微分方程

    1. 问题引入(有阻尼自由振动微分方程.有阻尼强迫振动微分方程) 2. n阶线性微分方程的一般形式(一阶线性微分方程的通解) 3. 二阶齐次线性微分方程.叠加原理 4. 函数组的线性相关及线性无关 5 ...

  3. 如何选择适合你的兴趣爱好(五十一),喝茶

    围城网的摇摇今天给大家带来了"如何选择适合你的兴趣爱好"系列专辑的第五十一讲--喝茶.茶不但是传统饮食文化,同时,由于茶中含有多种抗氧化物质与抗氧化营养素,对于消除自由基有一定的效 ...

  4. 乘法原理的例题和答案_【原创】奥数解析(五十一)加法原理和乘法原理

    五年级奥数解析(五十一)加法原理和乘法原理 <奥赛天天练>第五十一讲<加法原理和乘法原理>,进一步学习运用加法原理和乘法原理解答比较复杂的计数问题.有关加法原理和乘法原理的简要 ...

  5. 第二十一讲 特征值和特征向量

    我个人认为麻省理工线性代数这门课,到二十一讲才真正进入有用的部分,因此从这一讲开始做笔记. 一,概念 满足条件:Ax=λx 解释:当向量x经过矩阵A变换后,效果等于向量x乘上任意常数λ 则:x是矩阵A ...

  6. c语言里有js的预编译环节吗,C语言第十一讲,预处理命令.

    C语言第十一讲,预处理命令. 一丶预处理简介 什么是预处理,预处理就是预先处理. 我们知道,程序会经过编译,连接形成可执行文件 这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理.提前 ...

  7. 收藏 | 李飞飞经典CS231N《卷积神经网络视觉识别》第十一讲!

    点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:专知 AI博士笔记系列推荐 周志华<机器学习>手推笔记正式开源!可打印版本附pdf下载链接 [导读 ...

  8. c语言输入输出预处理命令,C语言第十一讲,预处理命令.

    C语言第十一讲,预处理命令. 一丶预处理简介 什么是预处理,预处理就是预先处理. 我们知道,程序会经过编译,连接形成可执行文件 这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理.提前 ...

  9. 【正点原子STM32连载】第五十一章 视频播放器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

最新文章

  1. centos8安装KVM/QEUM虚拟化
  2. 测试人员:如何品味软件的品位
  3. H3C RIPv2配置任务
  4. 仿微信公众平台“打标签”功能~~~
  5. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车超声波避障实验(无舵机)
  6. [BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)
  7. Fread 和fwrite的参数不同,返回值不同
  8. Nginx:限流、缓存、黑白名单等功能详解!
  9. mysql 并发数 任务调度_mysql的计划任务与事件调度实例分析
  10. hun 暑期实训之打牌 cin与scanf的输入
  11. cf的服务器型号,常用CF法兰的型号和尺寸表
  12. 详解30道Vue面试题
  13. 迪文屏用c语言控制按键触发,用迪文屏模拟了个加密键盘功能
  14. 艾美捷RPMI-1640培养基L-谷氨酰胺的参数和配方
  15. 容器类:QVector、QList、QSet、QMap使用
  16. Unity 安卓 apk 反编译 重新打包 签名修改
  17. 字节主管工程师年薪中位数 56.4 万美元,排世界第 7,2022 全球程序员收入报告出炉!...
  18. 如何理解统计中的特征函数?
  19. UG NX 12 对象的选择操作
  20. 什么是触发器?MySQL触发器概念及其应用解析

热门文章

  1. gcc 动态库的编译和使用
  2. Postgresql 全文检索测试
  3. Elasticsearch 参考指南(索引名中的日期公式支持)
  4. 我在千峰培训的日子第八天--------数组
  5. 苹果电脑macos Monterey 12.1(21C52)dmg原版引导版镜像下载
  6. matlab里的for循环,matlabfor循环
  7. WIN7上保护隐私的一些设置
  8. 碰撞检测算法之GJK算法
  9. GDCPC2016题解 by lby@SYSU | Asiimov
  10. 无限分类树--Treeview