簡體   English   中英

i2c 驅動程序啟動 - raspbian

[英]i2c driver boot up - raspbian

我對 linux 上的設備驅動程序比較陌生。 我試圖實現的是,在我的 Raspberry 啟動時,外部 RGB 驅動程序將收到一個 i2c 命令,因此您可以在啟動時看到 LED 亮起。

我的方法是嘗試通過將在啟動時加載的內核模塊來完成此操作。 我嘗試了很多方法來實現這一點,但目前我覺得我有知識差距。 也許有人可以幫助我? (請注意,這不是硬件問題,我可以從用戶空間向設備發送命令。)

我的內核模塊代碼如下:

    #include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/regmap.h>


MODULE_AUTHOR ("Niels");
MODULE_DESCRIPTION("driver rgb led");
MODULE_LICENSE("GPL");

/*CAT3626 control registers*/
#define CAT3626_ADDRESS     0x66
#define CAT3626_ENA         0x03
#define CAT3626_REGA        0x00
#define CAT3626_REGB        0x01
#define CAT3626_REGC        0x02

struct cat3626 {
    struct device *dev;
    struct regmap * regmap;
};


enum {
    cat3626, 
};

static const struct of_device_id cat3626_dt_ids[] = {
    { .compatible = "onsemi,cat3626", .data = (void *)cat3626},
    { }
};

MODULE_DEVICE_TABLE(of, cat3626_dt_ids);


static const struct i2c_device_id cat3626_id[] = {
    {"cat3626",cat3626},
    { }
};

MODULE_DEVICE_TABLE(i2c, cat3626_id);

static const struct regmap_config regmap_config = {
    .reg_bits = 8,
    .val_bits = 8,
};

static int cat3626_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct cat3626 *cat3626;
    const struct of_device_id *match;
    int ret;

    cat3626 = devm_kzalloc(&client->dev, sizeof(struct cat3626), GFP_KERNEL);
    if (!cat3626){
        return -ENOMEM;
    }

    dev_set_drvdata(&client->dev, cat3626);
    cat3626->dev = &client->dev;

    cat3626->regmap = devm_regmap_init_i2c(client, &regmap_config);
    if (IS_ERR(cat3626->regmap)) {
        dev_err(cat3626->dev, "regmap allocation failed\n");
        return PTR_ERR(cat3626->regmap);
    }

    i2c_set_clientdata(client, cat3626);

    match = of_match_device(cat3626_dt_ids, &client->dev);
        if (!match) {
        dev_err(&client->dev, "unknown device model\n");
        return -ENODEV;
    }

    ret = i2c_smbus_write_byte_data(client, CAT3626_ENA, 0x30);   /* write LED C on*/
    ret = i2c_smbus_write_byte_data(client, CAT3626_REGC, 19);    /* write mA*/

    return ret;
}

static struct i2c_driver cat3626_driver = {
    .driver = {
        .name = "cat3626",
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr(cat3626_dt_ids),
    },
    .probe = cat3626_probe,
    .remove = cat3626_remove,
    .id_table = cat3626_id,
};

module_i2c_driver(cat3626_driver);

這是生成文件:

ifneq ($(KERNELRELEASE),)
    obj-m := hiber_rgb_driver.o

else
    KERNELDIR ?= \
    /lib/modules/`uname -r`/build/
    PWD := `pwd`

default:
    $(MAKE) -C $(KERNELDIR) \
    M=$(PWD) modules

endif

clean:
    rm -f *.ko *.o Module* *mod*

在 /boot/config.txt 文件中,我添加了以下內容:

dtoverlay = i2c-gpio, bus = 80, i2c_gpio_delay_us = 2, i2c_gpio_sda = 44, i2c_gpio_scl = 45.

另外我做了一個自定義的dtoverlay:

/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target = <&i2c80>;
        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;

            cat3626: cat3626@66 {
                compatible = "onsemi,cat3626";
                reg = <0x66>;
                clock-frequency = <400000>;
            };
        };
    };
};

啟動時不幸沒有任何反應。 我從啟動 dmesg 得到的信息如下:

rgb_driver: loading out-of-tree module taints kernel

任何人都可以給我任何幫助,或者可能采用不同的方法來實現我的目標?

提前致謝!

需要注意的幾件事 - 受污染的內核通常會減少功能,如果不需要,您可能不想去那里。 我會嘗試解決污染問題。 我已經將內核模塊構建為獨立的並且沒有遇到污點問題。 您可能希望重新訪問您的 makefile,這是一個更標准的模塊構建 makefile,有一些皺紋,當然,您正在交叉編譯 -

PWD = $(shell pwd)
obj-m += hiber_rgb_driver.o

all:
    make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KERNEL) SUBDIRS=$(PWD) modules

clean:
    make -C $(KERNEL) SUBDIRS=$(PWD) clean

並用類似的東西構建它 -

make KERNEL=<LINUX_SOURCE_DIR> CROSS=<TOOLCHAIN_DIR>/bin/arm-linux-gnueabihf-

所以就是這樣。

接下來,您的設備探針看起來很有趣。 我沒有時間為您調試它,但我建議在其中添加一些 printk 以驗證探針是否被擊中。 如果是,那就太好了,這只是弄清楚為什么你不“匹配”的問題。 如果它沒有被擊中,請繼續閱讀..

您可能知道,i2c 總線在設備探測方面有點特殊。 沒有真正的自動化或神奇的探測,通常會發生在 PCI 總線上。 相反,您需要構建一個設備樹,內核可以在啟動時遍歷它以完成所有探測。

我看到您創建了一個疊加片段。 您需要確保該內容已編譯為內核可以解析的“.dtb”字節碼二進制文件,然后將其放在引導媒體中 grub 可以找到它的正確位置。

您可能還需要更新設備的主 dtb 以引用此覆蓋,以便內核知道它可能會去哪里。 將設備的 dtb 視為人造聖誕樹,而將覆蓋層視為可以在未來某個時間點連接的樹枝 - 您需要在設備 dtb 中指定連接點。 我希望我在這里可以更准確,但希望至少在這一點上讓你朝着正確的方向前進。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM