驱动
你好,我是拉依达。这是我的Linux驱动开发八股文详细解析系列。本系列最开始是我在csdn上更新的文章,目前已经是csdn搜索“linux驱动”综合推荐第一名,累计阅读次数4w次。全文总字数近8w字,是目前全网最全面,最清晰的入门linux驱动学习资料。现重新对内容进行整理,希望可以帮助到更多学习嵌入式的同学。【下面是拉依达推荐学习相关专栏:】 一、Linux驱动学习专栏:拉依达的Linux驱动八股文 - 牛客网 二、Linux应用学习专栏:拉依达的Linux应用八股文 - 牛客网 【我的嵌入式学习和校招经验】拉依达的嵌入式学习和秋招经验-CSDN博客 嵌入式学习规划/就业经验指导,可私信咨询———————————————————————————————————————————————————15.4 platform 总线框架例程一、应用层int main(int argc, char *argv[]){    int fd, retvalue;    char *filename;    unsigned char databuf[1];    unsigned char readbuf[1];    if(argc != 3)    {        printf("Error Usage!\r\n");        return -1;    }    filename = argv[1];    fd = open(filename, O_RDWR);    if(fd < 0)    {        printf("file %s open failed!\r\n", argv[1]);        return -1;    }    databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 */    if(databuf[0] ==  2)    {         retvalue = read(fd,readbuf,sizeof(readbuf));        if(retvalue < 0)        {            printf("read file %s failed!\r\n",filename);        }        else        {            printf("read date: %x\r\n",readbuf[0]);        }    }else    {         /* 向/dev/led 文件写入数据 */        retvalue = write(fd, databuf, sizeof(databuf));        if(retvalue < 0)        {            printf("LED Control Failed!\r\n");            close(fd);            return -1;        }    }       retvalue = close(fd);    if(retvalue < 0)    {        printf("file %s close failed!\r\n", argv[1]);        return -1;    }    return 0;}   二、驱动层(无设备树)device.c/*  * 寄存器地址定义 */#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/*   * 设备资源信息,也就是LED0所使用的所有寄存器 */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设备结构体  */static struct platform_device leddevice = { .name = "imx6ul-led", .id = -1, .dev = {  .release = &led_release, }, .num_resources = ARRAY_SIZE(led_resources), .resource = led_resources,};static int __init leddevice_init(void){ return platform_device_register(&leddevice);}static void __exit leddevice_exit(void){ platform_device_unregister(&leddevice);}module_init(leddevice_init);module_exit(leddevice_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("songwei");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{ ...... };struct leddev_dev leddev;  /* led设备 */static struct file_operations led_fops = { .owner = THIS_MODULE,    .read = led_read, .open = led_open, .write = led_write,};/* * @description  : flatform驱动的probe函数,当驱动与 *        设备匹配以后此函数就会执行 * @param - dev  : platform设备 * @return    : 0,成功;其他负值,失败 */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!\r\n"); /* 1、获取资源 */ for (i = 0; i < 5; i++) {  ledsource[i] = platform_get_resource(dev, IORESOURCE_MEM, i); /* 依次MEM类型资源 */  if (!ledsource[i]) {   dev_err(&dev->dev, "No MEM resource for always on\n");   return -ENXIO;  }  ressize[i] = resource_size(ledsource[i]);  }  ......}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); ......}/* platform驱动结构体 */static struct platform_driver led_driver = { .driver  = {  .name = "imx6ul-led",   /* 驱动名字,用于和设备匹配 */ }, .probe  = led_probe, .remove  = led_remove,};static int __init leddriver_init(void){ return platform_driver_register(&led_driver);}static void __exit leddriver_exit(void){ platform_driver_unregister(&led_driver);}module_init(leddriver_init);module_exit(leddriver_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("songwei");二、驱动层(有设备树)driver.c#define LEDDEV_CNT  1   /* 设备号长度  */#define LEDDEV_NAME  "dts_platled" /* 设备名字  */#define LEDOFF    0#define LEDON    1/* leddev设备结构体 */struct leddev_dev{ ......    struct device_node *node; /* LED设备节点 */ int led0;     /* LED灯GPIO标号 */ };struct leddev_dev leddev;  /* led设备 */static struct file_operations led_fops = { .owner = THIS_MODULE,    .read = led_read, .open = led_open, .write = led_write,};/* * @description  : flatform驱动的probe函数,当驱动与 *        设备匹配以后此函数就会执行 * @param - dev  : platform设备 * @return    : 0,成功;其他负值,失败 */static int led_probe(struct platform_device *dev){  ......    /* 6、初始化IO */  leddev.node = of_find_node_by_path("/gpioled"); if (leddev.node == NULL){  printk("gpioled node nost find!\r\n");  return -EINVAL; }  leddev.led0 = of_get_named_gpio(leddev.node, "led-gpio", 0); if (leddev.led0 < 0) {  printk("can't get led-gpio\r\n");  return -EINVAL; } gpio_request(leddev.led0, "led0"); gpio_direction_output(leddev.led0, 1); /* led0 IO设置为输出,默认高电平 */ return 0;}/* * @description  : platform驱动的remove函数,移除platform驱动的时候此函数会执行 * @param - dev  : platform设备 * @return    : 0,成功;其他负值,失败 */static int led_remove(struct platform_device *dev){    gpio_set_value(leddev.led0, 1);  /* 卸载驱动的时候关闭LED */ gpio_free(leddev.led0);    /* 释放IO    */ ......}/* 匹配列表 */static const struct of_device_id led_of_match[] = { { .compatible = "songwei-gpioled" }, { /* Sentinel */ }};/* platform驱动结构体 */static struct platform_driver led_driver = { .driver  = {  .name = "imx6ul-led",   /* 驱动名字,用于和设备匹配 */        .of_match_table = led_of_match, /* 设备树匹配表    */ }, .probe  = led_probe, .remove  = led_remove,};static int __init leddriver_init(void){ return platform_driver_register(&led_driver);}static void __exit leddriver_exit(void){ platform_driver_unregister(&led_driver);}module_init(leddriver_init);module_exit(leddriver_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("songwei");
点赞 8
评论 2
全部评论

相关推荐

和蔼:在竞争中脱颖而出,厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务