Embedded LINUX driver learning 14 software and hardware separation programming (2) code example (implemented through struct resource structure)

Embedded LINUX driver learning 14 software and hardware separation programming (two) code examples

1. Hardware information configuration

//btn_led_dev.c
include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct resource led_src_B[] = {
    
    
    {
    
        //用于保存寄存器地址
        .start = 0XC001B000,
        .end   = 0XC001B000 + 0X24,
        .flags = IORESOURCE_MEM
    },
    {
    
    
       用于保存GPIO号
        .start =26 ,
        .end   =26 ,
        .flags = IORESOURCE_IRQ
    }
};
static void dd_close(struct device *dev){
    
    }//WARNING: at drivers/base/core.c:196
static struct platform_device btn_led_dev= {
    
    
    .name = "LED_",//硬件驱动名称
    .id   = 1,//当有多个同名配件驱动时,用ID加以区分
    .dev = {
    
    
            .release = dd_close  //用于消除警告
        },
    .num_resources = 2,//一般可以用ARRAY_SIZE(led_src_B) ,即:数组元素个数
    .resource = led_src_B//数组首地址
};

static int btn_led_dev_init(void){
    
    
    platform_device_register(&btn_led_dev); // 注册硬件信息
    return 0;
}
static void btn_led_dev_exit(void){
    
    
    platform_device_unregister(&btn_led_dev_3); //释放硬件信息注册
}
module_init(btn_led_dev_init);
module_exit(btn_led_dev_exit);
MODULE_LICENSE("GPL");

2. Software driver code:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
void * ioremap_ret ;
unsigned long *base;
unsigned long *outenb;
unsigned long *altfn;
int myprobe(struct platform_device * pl_reg){
    
    
    struct resource *phy_src = platform_get_resource(pl_reg,IORESOURCE_MEM,0); //保存寄存器地址
    struct resource *gpio_src = platform_get_resource(pl_reg,IORESOURCE_IRQ,0);//保存GPIO号
    ioremap_ret = ioremap((phy_src ->start),0x24);//寄存器地址和虚拟地址的映射
    base   = (unsigned long *) ioremap_ret;//GPIO号对应寄存器首地址
    *base   &= ~(0x1 << gpio_src ->start);
    outenb = (unsigned long *) (ioremap_ret + 0x4);
    *outenb |=  (0x1 << gpio_src -> start);    
    if(gpio_src->start < 15){
    
    
        altfn  = (unsigned long *) (ioremap_ret +  0x20);
        *altfn &= ~(0x3 << (gpio_src ->start * 2));
        *altfn |=  (0x1 << (gpio_src ->start * 2));
    }
    else {
    
    
        altfn  = (unsigned long *) (ioremap_ret +  0x24);
        *altfn &= ~(0x3 << ((gpio_src -> start - 16) * 2));
        *altfn |=  (0x1 << ((gpio_src -> start - 16) * 2));
    }
    return 0;
}
int myremove(struct platform_device *pl_rem){
    
    
    struct resource *phy_src = platform_get_resource(pl_rem,IORESOURCE_MEM,0);
    struct resource *gpio_src = platform_get_resource(pl_rem,IORESOURCE_IRQ,0);
    ioremap_ret = ioremap(phy_src ->start,0x24);
    base   = (unsigned long *) ioremap_ret;
    *base   |= (0x1 << gpio_src -> start);
    return 0;
}

struct platform_driver bl_pd = {
    
    
    .probe = myprobe,
    .remove = myremove,
    .driver = {
    
    
        .name = "LED_" //用做和硬件驱动的匹配名称
    }
};

static int btn_led_init(void){
    
    
    platform_driver_register(&bl_pd);
    return 0;
}
static void btn_led_exit(void){
    
    
    platform_driver_unregister(&bl_pd);
}
module_init(btn_led_init);
module_exit(btn_led_exit);
MODULE_LICENSE("GPL");
                                  

Guess you like

Origin blog.csdn.net/weixin_47273317/article/details/108295744