Device.c文件:
- 设备释放函数
- 设备的资源信息
- platform_device结构体
- 设备初始化函数
- 设备退出函数
文件中涉及到的定义:
/* 寄存器的物理地址 */ #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