首页 > 其他分享 >Platform平台总线模型

Platform平台总线模型

时间:2023-03-09 23:14:23浏览次数:34  
标签:GPIO1 led struct 模型 总线 Platform BASE static device

Device.c文件:

  1. 设备释放函数
  2. 设备的资源信息
  3. platform_device结构体
  4. 设备初始化函数
  5. 设备退出函数

 

文件中涉及到的定义:

/* 寄存器的物理地址 */
#define CCM_CCGR1_BASE          (0x020C406C)
#define SW_MUX_GPIO1_IO03_BASE  (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE  (0X020E02F4)
#define GPIO1_DR_BASE           (0X0209C000)
#define GPIO1_GDIR_BASE         (0X0209C004)

#define REGISTER_LENGTH         4

 

设备释放函数:

/* 释放flatform 设备模块的时候此函数会执行 */
static void led_release(struct device *dev)
{
    printk("led device release\n");
}

 

设备的资源信息:

static struct resource led_resources[] = {
    [0] = {
        .start = CCM_CCGR1_BASE,
        .end   = (CCM_CCGR1_BASE + REGISTER_LENGTH - 1),
        .flags = IORESOURCE_MEM,
    },

    [1] = {
        .start = SW_MUX_GPIO1_IO03_BASE,
        .end   = {SW_MUX_GPIO1_IO03_BASE + REGISTER_LENGTH - 1},
        .flags = IORESOURCE_MEM,
    },
    
    [2] = {
        .start = SW_PAD_GPIO1_IO03_BASE,
        .end   = {SW_PAD_GPIO1_IO03_BASE + REGISTER_LENGTH - 1},
        .flags = IORESOURCE_MEM,
    },

    [3] = {
        .start = GPIO1_DR_BASE,
        .end   = {GPIO1_DR_BASE + REGISTER_LENGTH - 1},
        .flags = IORESOURCE_MEM,
    },

    [4] = {
        .start = GPIO1_GDIR_BASE,
        .end   = {GPIO1_GDIR_BASE + REGISTER_LENGTH - 1},
        .flags = IORESOURCE_MEM,
    },
};

 

platform_device 结构体:

static struct platform_device leddevice = {
    .name = "imx6ul-led",
    .id = -1,
    .dev = {
        .release = &led_release,
    },
    .num_resources = ARRAY_SIZE(led_resources),
    .resource = led_resources,
};

 

device的init函数:

static int __init leddevice_init(void)
{
    return platform_device_register(&leddevice);
}

 

device的exit函数:

static void __exit leddevice_exit(void)
{
    platform_device_unregister(&leddevice);
}

 

module_init(leddevice_init);
module_exit(leddevice_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("huaimin");

 

 

Driver.c文件:

文件中涉及到的定义:

#define LEDDEV_CNT  1           /* 设备号长度 */
#define LEDDEV_NAME "platled"   /* 设备名字 */
#define LEDOFF      0
#define LEDON       1

 

虚拟映射寄存器名:

/* 寄存器名 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;

 

定义设备的驱动结构体:

/* leddev 设备结构体 */
struct leddev_dev{
    dev_t devid;            /* 设备号 */
    struct cdev cdev;       /* cdev  */
    struct class *class;    /* 类    */
    struct device *device;  /* 设备 */

    int major;
    int minor;
};

struct leddev_dev leddev;

 

灯开关切换函数:

void led0_switch(u8 state)
{
    u32 retValue;
    
    retValue = readl(GPIO1_DR);

    if(state == LEDON)
    {
        retValue &= ~(1<<3);
        writel(retValue, GPIO1_DR);
    }
    else if(state == LEDOFF)
    {
        retValue |= (1<<3);
        writel(retValue, GPIO1_DR);
    }
}

 

设备驱动open函数:

static int led_open(struct inode *inode, struct file *filp)
{
    filp -> private_data = &leddev; /* 设置私有数据 */
    return 0;
}

 

设备驱动write函数:

static ssize_t led_write(struct file* filp, const char __user *buf, size_t cnt,loff_t *offt)
{
    int retValue;
    unsigned char databuf[1];
    unsigned char ledstate;

    retValue = copy_from_user(databuf, buf, cnt);
    if(retValue < 0)
    {
        return -1;
    }

    ledstate = databuf[0];
    if(ledstate == LEDON){
        led0_switch(LEDON);
    }else if(ledstate == LEDOFF)
    {
        led0_switch(LEDOFF);
    }
    return 0;
}

 

设备驱动文件操作结构体:

static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
};

 

Platform_driver的probe函数:

static int led_probe(struct platform_device *dev)
{
    int i = 0;
    int ressize[5];
    u32 val = 0;
    struct resource *ledsource[5];

    printk("led driver and device has matched!\n");

    /*  1、获取资源    */
    for(i = 0; i < 5;i++)
    {
        ledsource[i] = platform_get_resource(dev, IORESOURCE_MEM, i);
        if(!ledsource[i]){
            dev_err(&dev->dev, "NO MEM RESOURCE FOR ALWAYS ON\n");
            return -1;
        }
        ressize[i] = resource_size(ledsource[i]);
    }

    /*  2、初始化LED    */
    /* 寄存器地址映射 */
    IMX6U_CCM_CCGR1 = ioremap(ledsource[0]->start, ressize[0]);
    SW_MUX_GPIO1_IO03 = ioremap(ledsource[1]->start, ressize[1]);
    SW_PAD_GPIO1_IO03 = ioremap(ledsource[2]->start, ressize[2]);
    GPIO1_DR        = ioremap(ledsource[3]->start,  ressize[3]);
    GPIO1_GDIR       = ioremap(ledsource[4]->start, ressize[4]);


    /* 启动时钟 */
    val = readl(IMX6U_CCM_CCGR1);
    val |= (3<<26);
    writel(val, IMX6U_CCM_CCGR1);

    /* 设置GPIO1_IO03复用功能 */
    writel(5, SW_MUX_GPIO1_IO03);
    writel(0x10B0, SW_PAD_GPIO1_IO03);


    /* 设置GPIO1_IO03 为输出功能 */
    val = readl(GPIO1_GDIR);
    val |= (1<<3);
    writel(val, GPIO1_GDIR);

    /* 默认关闭LED1 */
    val = readl(GPIO1_DR);
    val |= (1<<3);
    writel(val, GPIO1_DR);

    /* 注册字符设备驱动 */
    if(leddev.major) //定义了字符设备的主设备号
    {
        leddev.devid = MKDEV(leddev.major, 0);
        register_chrdev_region(leddev.devid, LEDDEV_CNT, LEDDEV_NAME);
    }
    else
    {
        alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);
        leddev.major = MAJOR(leddev.devid);
        leddev.minor = MINOR(leddev.devid);
    }
    printk("newchrdev major = %d, minor = %d \r\n",leddev.major,leddev.minor);

    
    /* 初始化 cdev */
    leddev.cdev.owner = THIS_MODULE;
    cdev_init(&leddev.cdev, &led_fops);

    /* 添加一个cdev */
    cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
    
    /* 创建类 */
    leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
    if(IS_ERR(leddev.class)){
        return PTR_ERR(leddev.class);
    }

    /* 创建设备 */
    leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);
    if(IS_ERR(leddev.device)){
        return PTR_ERR(leddev.device);
    }

    return 0;
}

 

Platform_driver的remove函数:

static int led_remove(struct platform_device *dev)
{
    iounmap(IMX6U_CCM_CCGR1);
    iounmap(SW_MUX_GPIO1_IO03);
    iounmap(SW_PAD_GPIO1_IO03);
    iounmap(GPIO1_DR);
    iounmap(GPIO1_GDIR);

    cdev_del(&leddev.cdev);
    unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
    device_destroy(leddev.class, leddev.devid);
    class_destroy(leddev.class);

    return 0;
}

 

Platform_driver结构体:

static struct platform_driver led_driver = {
    .driver = {
        .name = "imx6ul-led",
    },
    .probe = led_probe,
    .remove = led_remove,
};

 

driver的init函数:

static int __init leddriver_init(void)
{
    return platform_driver_register(&led_driver);
}

 

driver的exit函数:

static void __exit leddriver_exit(void)
{
    platform_driver_unregister(&led_driver);
}

 

module_init(leddriver_init);
module_exit(leddriver_exit);
MODULE_LICENSE("GPL");

 

 

测试App文件:

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"

#define LEDON  1
#define LEDOFF 0

int main(int argc,char* argv[])
{
    int fd,retValue;
    char* fileName;
    if(argc != 3)
    {
        printf("Error Usage!\r\n");
        return -1;
    }

    fileName = argv[1];

    fd = open(fileName, O_RDWR);
    if(fd < 0)
    {
        printf("open %s file failed!\r\n", argv[1]);
        return -1;
    }

    //char dataBuf[1] 用于接收来自与控制台传输的数据 

    unsigned char dataBuf[1];

    dataBuf[0] = atoi(argv[2]);

    retValue = write(fd, dataBuf, 1);

    if(retValue < 0)
    {
        printf("Write file failed\r\n");
        close(fd);
        return -1;
    }

    retValue = close(fd);
    if(retValue < 0)
    {
        printf("close file failed \r\n");
        return -1;
    }

    return 0;
}

 

标签:GPIO1,led,struct,模型,总线,Platform,BASE,static,device
From: https://www.cnblogs.com/huaimin0304/p/17201850.html

相关文章