第五十一讲 platform

第五十一讲 platform

一、前言

说几句题外话,因为是跟着视频再看,前面的东西我也是懵懵懂懂。随着后面的一些学习,其实前面差不多就是后面的一些基础。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_COMPILE

obj-m := dev.o drv.o

all:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean copy

clean:
	$(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!
    

四、其他

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值