組み込みLINUXドライバーが14のソフトウェアとハードウェアの分離プログラミング(3)コード例を学習(struceデバイスメンバーvoid * platform_dataによって実装)

組み込みLINUXドライバーが14のソフトウェアとハ​​ードウェアの分離プログラミング(3)コード例を学習(struceデバイスメンバーvoid * platform_dataによって実装)

1.コード例(ハードウェア情報の定義)

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
/*定义结构体对象,用于保存LED灯硬件信息
     phy_addr :用于保存寄存器的物理地址 
     gpio     :用于保存LED灯所在的GPIO编号
*/
struct led_phy_struct  {
    
    
    unsigned long phy_addr;
    int gpio;
};
struct led_phy_struct led_phy_obj[] ={
    
    
    {
    
    
        .phy_addr = 0XC001B000,
        .gpio     = 26
    },
    {
    
    
        .phy_addr = 0XC001C000,
        .gpio     = 11
    },
    {
    
    
        .phy_addr = 0XC001C000,
        .gpio     = 7
    },
    {
    
    
        .phy_addr = 0XC001C000,
        .gpio     = 12
    },
    {
    
    
        .phy_addr = 0,//做为数组结束标志
        .gpio     = 0
    }
};

void dd_close(struct device *dev){
    
    };//用于消除警告
struct platform_device pd_myled_struct = {
    
    
    .name = "LED_",
    .id   = 1,

    .dev  = {
    
    
        .platform_data = led_phy_obj,
        .release = dd_close
    }
};

static int myled_init(void){
    
    
    platform_device_register(&pd_myled_struct);
    return 0;
}
static void myled_exit(void){
    
    
    platform_device_unregister(&pd_myled_struct);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

2.コード例(ソフトウェア駆動)

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
/*
   定义和硬件信息匹配的结构体对象,用于获取硬件信息
*/
struct led_phy_struct {
    
    
    unsigned long phy_addr ;
    int gpio;
};
struct  led_phy_struct *led_phy_obj;

int myled_probe(struct platform_device * pd){
    
    
    int i = 0;
    void * void_addr;
    unsigned long *base,*outenb,*altfn;
    led_phy_obj = (struct led_phy_struct *)pd->dev.platform_data;
    while(led_phy_obj[i].phy_addr != 0){
    
    //当phy_addr == 0时,为硬件信息结构体结束标志
        void_addr = ioremap(led_phy_obj[i].phy_addr,0x24);
        base     =  (unsigned long *)void_addr;
        outenb   =  (unsigned long *)(void_addr+0x4);
        altfn    =   (unsigned long *)(void_addr + 0x20);
        *base   &= ~(0x1 << led_phy_obj[i].gpio);
        *outenb  |=  (0x1 << led_phy_obj[i].gpio);
        if(led_phy_obj[i].gpio < 15){
    
    
            altfn    =   (unsigned long *)(void_addr + 0x20);
            *altfn &= ~(0x3 << (led_phy_obj[i].gpio * 2));
            *altfn |=  (0x1 << (led_phy_obj[i].gpio * 2));
        }
        else {
    
    
            altfn    =   (unsigned long *)(void_addr + 0x24);
            *altfn &= ~(0x3 << ((led_phy_obj[i].gpio- 16) * 2));
            *altfn |=  (0x1 << ((led_phy_obj[i].gpio- 16) * 2));
        }
        iounmap(void_addr);
        i ++ ;
    }
    return 0;
}
static int myled_remove(struct platform_device *pd){
    
    
    int i = 0;
    void * void_addr;
    unsigned long *base;
    led_phy_obj = (struct led_phy_struct *)pd->dev.platform_data;
    while(led_phy_obj[i].phy_addr != 0){
    
    
        void_addr = ioremap(led_phy_obj[i].phy_addr,0x24);
        base     =  (unsigned long *)void_addr;
        *base |= (0x1 << led_phy_obj[i].gpio);
        iounmap(void_addr);
        i ++;
    }
    return 0;
}

struct platform_driver pd_myled_struct = {
    
    
    .probe  = myled_probe,
    .remove = myled_remove,
    .driver = {
    
    
        .name = "LED_"
    }
};

static int myled_drv_init(void){
    
    
    platform_driver_register(&pd_myled_struct);
    return 0;
}
static void myled_drv_exit(void){
    
    
    platform_driver_unregister(&pd_myled_struct);
}
module_init(myled_drv_init);
module_exit(myled_drv_exit);
MODULE_LICENSE("GPL");

おすすめ

転載: blog.csdn.net/weixin_47273317/article/details/108308753