我所理解的linux kernel的移植

来源:互联网 发布:朝鲜妹子 知乎 编辑:程序博客网 时间:2024/06/17 10:43

从林纳斯.托瓦兹(Linus B. Torvalds)执掌的网站www.kernel.org下载linux内核,比如:linux-4.9.30.tar.gz,解压:tar zxf linux-4.9.30.tar.gz,进入目录:cd linux-4.9.30,配置:make ARCH=arm64 menuconfig,编译:make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image,结果完全无警告、无错误地编译通过了,说明它是一个完整的源代码,但却无法拷贝至手机、机顶盒或开发板中使用,因为还未为其移植”驱动程序”。
 kernel是一套完整的源码,就象一张”会计报表”一样,为”驱动程序”留有很多空格,用于填写数据(函数指针)。比如,gpio驱动,内核定义一个struct gpio_chip,如下:

struct gpio_chip {    const char      *label;    struct gpio_device  *gpiodev;    struct device       *parent;    struct module       *owner;    int         (*request)(struct gpio_chip *chip,                        unsigned offset);    void            (*free)(struct gpio_chip *chip,                        unsigned offset);    int         (*get_direction)(struct gpio_chip *chip,                        unsigned offset);    int         (*direction_input)(struct gpio_chip *chip,                        unsigned offset);    int         (*direction_output)(struct gpio_chip *chip,                        unsigned offset, int value);    int         (*get)(struct gpio_chip *chip,                        unsigned offset);    void            (*set)(struct gpio_chip *chip,                        unsigned offset, int value);    void            (*set_multiple)(struct gpio_chip *chip,                        unsigned long *mask,                        unsigned long *bits);    int         (*set_debounce)(struct gpio_chip *chip,                        unsigned offset,                        unsigned debounce);    int         (*set_single_ended)(struct gpio_chip *chip,                        unsigned offset,                        enum single_ended_mode mode);#ifdef CONFIG_AMLOGIC_PINCTRL    int         (*set_pull)(struct gpio_chip *chip,                        unsigned int offset, int value);#endif    int         (*to_irq)(struct gpio_chip *chip,                        unsigned offset);    void            (*dbg_show)(struct seq_file *s,                        struct gpio_chip *chip);    int         base;    u16         ngpio;    const char      *const *names;    bool            can_sleep;    bool            irq_not_threaded;#if IS_ENABLED(CONFIG_GPIO_GENERIC)    unsigned long (*read_reg)(void __iomem *reg);    void (*write_reg)(void __iomem *reg, unsigned long data);    unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin);    void __iomem *reg_dat;    void __iomem *reg_set;    void __iomem *reg_clr;    void __iomem *reg_dir;    int bgpio_bits;    spinlock_t bgpio_lock;    unsigned long bgpio_data;    unsigned long bgpio_dir;#endif#ifdef CONFIG_GPIOLIB_IRQCHIP    /*     * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib     * to handle IRQs for most practical cases.     */    struct irq_chip     *irqchip;    struct irq_domain   *irqdomain;    unsigned int        irq_base;    irq_flow_handler_t  irq_handler;    unsigned int        irq_default_type;    int         irq_parent;    bool            irq_need_valid_mask;    unsigned long       *irq_valid_mask;    struct lock_class_key   *lock_key;#endif#if defined(CONFIG_OF_GPIO)    /*     * If CONFIG_OF is enabled, then all GPIO controllers described in the     * device tree automatically may have an OF translation     */    struct device_node *of_node;    int of_gpio_n_cells;    int (*of_xlate)(struct gpio_chip *gc,            const struct of_phandle_args *gpiospec, u32 *flags);#endif};

结构中的(*request)、(*free)、(*get_direction)、(*direction_input)等在移植前都是”空指针”,能被编译但却无法使用,需要我们根据具体的SOC芯片的数据编写一个个具体的、能工作的函数,并将函数的指针”填充”到gpio_chip结构中去,再调用gpiochip_add()函数一下,内核和应用程序就可以调用我们编写的驱动程序了。

domain->chip.label = domain->data->name;/* domain->chip.dev = pc->dev; */domain->chip.parent = pc->dev;domain->chip.request = meson_gpio_request;domain->chip.free = meson_gpio_free;domain->chip.direction_input = meson_gpio_direction_input;domain->chip.direction_output = meson_gpio_direction_output;domain->chip.get = meson_gpio_get;domain->chip.set = meson_gpio_set;domain->chip.set_pull = meson_gpio_pull_set;domain->chip.base = domain->data->pin_base;domain->chip.ngpio = domain->data->num_pins;domain->chip.can_sleep = false;domain->chip.of_node = domain->of_node;domain->chip.of_gpio_n_cells = 2;ret = gpiochip_add(&domain->chip);

上面这段程序就是填充的过程。
以此来推,其它驱动也是”类似”填充的。

原创粉丝点击