溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

芯靈思Sinlinx A64 linux 通過(guò)設(shè)備樹(shù)寫(xiě)LED

發(fā)布時(shí)間:2020-06-26 14:47:45 來(lái)源:網(wǎng)絡(luò) 閱讀:328 作者:sinlinx123 欄目:系統(tǒng)運(yùn)維

開(kāi)發(fā)平臺(tái) 芯靈思Sinlinx A64

內(nèi)存: 1GB 存儲(chǔ): 4GB
詳細(xì)參數(shù) https://m.tb.cn/h.3wMaSKm
開(kāi)發(fā)板交流群 641395230

全志A64設(shè)備樹(shù)結(jié)構(gòu)體

#include <linux/of.h> //設(shè)備樹(shù)里的每個(gè)設(shè)備及每個(gè)設(shè)備子節(jié)點(diǎn)都用此結(jié)構(gòu)體描述

struct device_node
{
    const char *name;
    const char *type;
    phandle phandle;
    const char *full_name;
    struct property *properties; //屬性
    struct property *deadprops; /* removed properties */
    struct device_node *parent; //在設(shè)備子節(jié)點(diǎn)對(duì)象,指向?qū)儆诘脑O(shè)備對(duì)象
    struct device_node *child; //在設(shè)備對(duì)象,指向子節(jié)點(diǎn)
    struct device_node *sibling; //指向同級(jí)的下一個(gè)對(duì)象.
    struct device_node *next; /* next device of same type */ //應(yīng)是指向device_type是同樣的對(duì)象
    struct device_node *allnext; /* next in list of all nodes */ ...
};

//下面函數(shù)用于獲取設(shè)備樹(shù)里的設(shè)備節(jié)點(diǎn)及設(shè)備子節(jié)點(diǎn)
extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
//通過(guò)名字查找相應(yīng)的設(shè)備節(jié)點(diǎn)
static inline int of_get_child_count(const struct device_node *np);
//獲取指定設(shè)備的子節(jié)點(diǎn)個(gè)數(shù)
extern struct device_node *of_find_node_by_path(const char *path);
//通過(guò)路徑來(lái)獲取設(shè)備節(jié)點(diǎn),可用于獲取設(shè)備子節(jié)點(diǎn)
extern struct device_node *of_find_node_by_type(struct device_node *from, const char *type); //通過(guò)指定的device_type來(lái)獲取設(shè)備節(jié)點(diǎn)

//下面函數(shù)用于獲取設(shè)備節(jié)點(diǎn)或設(shè)備子節(jié)點(diǎn)的屬性

static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value)
extern int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value);
extern int of_property_read_u8_array(const struct device_node *np, const char *propname, u8 *out_values, size_t sz);
extern int of_property_read_u16_array(const struct device_node *np, const char *propname, u16 *out_values, size_t sz);
extern int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz);
extern int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value);
extern int of_property_read_string(struct device_node *np, const char *propname, const char **out_string)

首先增加節(jié)點(diǎn),修改dtsi文件。
vim /lichee/linux-3.10/arch/arm64/boot/dts/sun50iw1p1-pinctrl.dtsi
芯靈思Sinlinx A64 linux 通過(guò)設(shè)備樹(shù)寫(xiě)LED

芯靈思Sinlinx A64 linux 通過(guò)設(shè)備樹(shù)寫(xiě)LED

驅(qū)動(dòng)代碼:

    #include <linux/module.h>   
    #include <linux/init.h>  
    #include <linux/fs.h>   
    #include <linux/device.h>   
    #include <linux/slab.h>  
    #include <linux/cdev.h>  
    #include <asm/uaccess.h>  
    #include <linux/io.h>  
    #include <linux/of.h>  
    #include <linux/of_gpio.h>  
    #include <linux/gpio.h>  
    #include <linux/sys_config.h>  

    #define MY_DEVICE_NAME "my_led_device"  
    // 獲取到設(shè)備樹(shù)中到節(jié)點(diǎn)  
    static int gpio = -1;   
    int get_irqno_from_node(void)  
    {  

        struct gpio_config config;   
        struct device_node *np = of_find_node_by_path("/leds");  
        if(np){  
            printk("find node ok\n");  
        }  
        else{  
            printk("find node failed\n");  
        }  

        gpio = of_get_named_gpio_flags(nd, "gpios", i, (enum of_gpio_flags *)&config);// 從設(shè)備樹(shù)中讀取gpios的GPIO配置編號(hào)和標(biāo)志  
        if(!gpio_is_valid(gpio)){  
            //判斷該 GPIO 編號(hào)是否有效,有效gpio_request 則申請(qǐng)占用該 GPIO。如果初始化過(guò)程出錯(cuò),需要調(diào)用 gpio_free 來(lái)釋放之前申請(qǐng)過(guò)且成功的 GPIO   
            printk("gpio isn't valid\n");  
            return -1;  
        }  
        if(gpio_request(gpio, "leds") < 0)   
            printk("gpio request failed %d\n", gpio);   
        gpio_direction_output(gpio, 1); //關(guān)燈  

        return 0;   

    }  

    static int my_open (struct inode *node, struct file *filp)  
    {  
        if(gpio)   
        {  
            printk("open ok\n");   
        }  
        else   
        {  
            return -EINVAL;  
        }  
        return 0;  
    }  

    static ssize_t my_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)  
    {  
        unsigned char val;          
        copy_from_user(&val, buf, 1);  
        printk(" gpl_dat address   0x%x\n",gpl_dat);  
        if (val)  
        {      
            gpio_direction_output(gpio, 0); //關(guān)燈  
            printk("led on\n");  
        }  
        else  
        {  
           gpio_direction_output(gpio, 1); //關(guān)燈  
            printk("led off\n");  
        }  

        return 1;   
    }  

    static const struct file_operations my_led_fops = {  
        //step 1 :定義file_operations結(jié)構(gòu)體  
        .open = my_open,  
        .write = my_write,      
    };  

    //step 1 :  
    static struct class *led_class;  
    static struct cdev *pcdev;      //定義一個(gè)cdev指針  
    static dev_t n_dev;            //第一個(gè)設(shè)備號(hào)(包含了主和次)  
    static int __init led_device_init(void)  
    {//step 2 :注冊(cè)   
        int ret = -1;  
        pcdev = cdev_alloc();//分配cdev結(jié)構(gòu)空間  
        if(pcdev == NULL) {  
            printk(KERN_EMERG" cdev_alloc  error\n");  
            ret = -ENOMEM;   /* 分配失敗 */  
            return ret;  
        }  
        //2. 動(dòng)態(tài)申請(qǐng)?jiān)O(shè)備號(hào)  
        ret = alloc_chrdev_region(&n_dev, 0 , 2, MY_DEVICE_NAME);  
        if(ret < 0 ) {  
            //釋放前面成功的資源  
            kfree(pcdev);                              /*釋放cdev結(jié)構(gòu)空間 */  
            printk(KERN_EMERG"alloc_chrdev_region  error\n");  
            return ret;  
        }      
        cdev_init(pcdev, &my_led_fops);     //初始化cdev結(jié)構(gòu)           /* 建立cdev和file_operations之間的連接 */   
        /* 
            或這樣初始化cdev結(jié)構(gòu) 
            pcdev->owner = THIS_MODULE; 
            pcdev->ops = &my_led_fops; 
        */  
        ret = cdev_add(pcdev, n_dev, 2) ;// 向內(nèi)核里面添加一個(gè)驅(qū)動(dòng),注冊(cè)驅(qū)動(dòng)  
        if(ret < 0 ) {  
            //釋放前面成功的資源  
            unregister_chrdev_region(n_dev,  2);       /*  釋放前面申請(qǐng)的調(diào)和號(hào)*/  
            kfree(pcdev);                               /* 釋放cdev結(jié)構(gòu)空間 */  
            printk(KERN_EMERG"alloc_chrdev_region  error\n");  
            return ret;  
        }  

        /*自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)/dev/SinlinxA64_LED*/  
        led_class = class_create(THIS_MODULE, "myled");      
        device_create(led_class, NULL, n_dev, NULL, "SinlinxA64_LED");   

        get_irqno_from_node();  
        printk(KERN_EMERG"cdev ok\n");      
        return 0;  
    }  

    static void __exit led_device_exit(void)  
    {    //step 2 :注銷(xiāo)  

        //注銷(xiāo)cdev結(jié)構(gòu)  
        cdev_del(pcdev);  
        //釋放設(shè)備號(hào)  
        unregister_chrdev_region(n_dev, 2); /*起始設(shè)備號(hào)(主、次) 連續(xù)的次設(shè)備號(hào)數(shù)量*/  
        //釋放cdev結(jié)構(gòu)空間  
        kfree(pcdev);  

        device_destroy(led_class, n_dev);  
        class_destroy(led_class);  
        gpio_free(gpio);   
        printk(KERN_EMERG"cdev_del ok\n");  
    }  

    module_init(led_device_init);  
    module_exit(led_device_exit);  
    MODULE_LICENSE("GPL");  

參考文章:https://blog.csdn.net/jklinux/article/details/82382066

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI