1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Linux设备驱动 | LED字符设备驱动(platform平台总线)

Linux设备驱动 | LED字符设备驱动(platform平台总线)

时间:2020-03-21 06:31:08

相关推荐

Linux设备驱动 | LED字符设备驱动(platform平台总线)

platform平台总线实现LED字符设备驱动

参考内核中存在的字符设备驱动进行编写,如misc.c这个经典的字符设备驱动。

一、LED字符设备驱动平台设备实现

1、查看手册获取相关寄存器

寄存器宏定义:

#define CCM_CCGR10x20C406C //打开/关闭时钟的寄存器地址 : 使用一个模块前必须开发它的使用,默认是打开的#define MUX_PAD_GPIO1_IO040x20E006C //GPIO复用寄存器地址 : 复用pin为GPIO功能还是其他功能#define GPIO1_DR0x209C000 //GPIO输入输出寄存器地址#define GPIO1_GDIR 0x209C004 //GPIO方向寄存器 :设置GPIO为输入还是输出模式#define REG_LEN 4 //寄存器地址长度

对于GPIO的配置使用和STM32等单片机使用寄存器开发是一样的。

2、定义硬件资源描述struct resource

static struct resource red_led_resource[] = {[0] = {.start = CCM_CCGR1,.end = (CCM_CCGR1 + REG_LEN - 1),.flags = IORESOURCE_MEM,},[1] = {.start = MUX_PAD_GPIO1_IO04,.end = (MUX_PAD_GPIO1_IO04 + REG_LEN - 1),.flags = IORESOURCE_MEM,},[2] = {.start = GPIO1_DR,.end = (GPIO1_DR + REG_LEN - 1),.flags = IORESOURCE_MEM,},[3] = {.start = GPIO1_GDIR,.end = (GPIO1_GDIR + REG_LEN - 1),.flags = IORESOURCE_MEM,},};

对于硬件的操作就是对寄存器的操作,而硬件的寄存器是映射到内存地址上的,所以就是操作内存。所以flags资源类型选择的是IORESOURCE_MEM,start - 寄存器的其实地址,end - 寄存器的结束地址。

3、定义平台设备

static void red_led_platform_release(struct device *dev){}static struct platform_device red_led_device = {.name = "red_led",.id = -1,.resource = red_led_resource, //注入硬件资源.num_resources = ARRAY_SIZE(red_led_resource), //硬件资源数组大小.dev.release = red_led_platform_release,};

4、平台设备入口函数

static int __init red_led_platform_device_init(void){printk("red_led_platform_device_init\r\n");int ret = platform_device_register(&red_led_device);return ret;}module_init(red_led_platform_device_init);

platform_device_register - 注册平台设备

5、平台设备出口函数

static void __exit red_led_platform_device_exit(void){printk("red_led_platform_device_exit\r\n");platform_device_unregister(&red_led_device);}

platform_device_unregister - 卸载平台设备驱动

二、LED字符设备平台驱动实现

平台设备的struct file_operations结构函数还是和传统方式一样的实现。

对于平台驱动方式实现的led驱动的变化:

1、定义平台驱动

static struct platform_driver red_led_platform_driver = {.probe = led_red_driver_probe,.remove = led_red_driver_remove,.driver.name = "red_led",};

.driver.name 字段的值red_led和平台设备中的name字段一致,表示通过名字进行平台设备和驱动的匹配

2、在probe()函数中进行初始化工作

static int led_red_driver_probe(struct platform_device *dev){struct resource *ccm_ccgr1 = platform_get_resource(dev, IORESOURCE_MEM, 0); //获取设备中定义的文件资源struct resource *mux_pad_gpio1_io4 = platform_get_resource(dev, IORESOURCE_MEM, 1);struct resource *gpio1_dr = platform_get_resource(dev, IORESOURCE_MEM, 2);struct resource *gpio1_gdir = platform_get_resource(dev, IORESOURCE_MEM, 3);if (ccm_ccgr1 == NULL || mux_pad_gpio1_io4 == NULL || gpio1_dr == NULL || gpio1_gdir == NULL)return -1;_CCM_CCGR1 = ioremap(ccm_ccgr1->start, resource_size(ccm_ccgr1)); //将寄存器物理地址映射为虚拟地址_MUX_PAD_GPIO1_IO04 = ioremap(mux_pad_gpio1_io4->start, resource_size(mux_pad_gpio1_io4));_GPIO1_DR = ioremap(gpio1_dr->start, resource_size(gpio1_dr));_GPIO1_GDIR = ioremap(gpio1_gdir->start, resource_size(gpio1_gdir)); int err;major = register_chrdev(0, "my_led", &led_drv);led_class = class_create(THIS_MODULE, "my_led_class");err = PTR_ERR(led_class);if (IS_ERR(led_class)) {unregister_chrdev(major, "my_led"); return -1;}device_create(led_class, NULL, MKDEV(major, 0), NULL, "my_led"); printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;}

struct resource *ccm_ccgr1 = platform_get_resource(dev, IORESOURCE_MEM, 0) - 获取平台设备定义的硬件资源_CCM_CCGR1 = ioremap(ccm_ccgr1->start, resource_size(ccm_ccgr1) - 将寄存器物理地址映射为虚拟地址

3、在remove()函数中做卸载/解初始化工作

int led_red_driver_remove(struct platform_device *dev){iounmap(_CCM_CCGR1);iounmap(_MUX_PAD_GPIO1_IO04);iounmap(_GPIO1_DR);iounmap(_GPIO1_GDIR);printk(" %s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, "my_led");return 0;}

4、平台设备的注册/卸载

//平台设备入口函数static int __init red_led_driver_init(void){printk(" %s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);int ret = platform_driver_register(&red_led_platform_driver);return ret;}//平台设备出口函数static void __exit red_led_driver_exit(void){printk(" %s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);platform_driver_unregister(&red_led_platform_driver);}module_init(red_led_driver_init);module_exit(red_led_driver_exit);MODULE_AUTHOR("Ares");MODULE_LICENSE("GPL");

5、加载/卸载驱动

sudo insmod platform_led_device.ko//安装led platform devicesudo insmod platform_led_driver.ko//安装led platform driver

在加载设备和驱动匹配成功后,会在系统目录/sys/bus/platform/devices//sys/bus/platform/driver/*出现相应led deviceled driver的目录

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。