kernel:module_init模块加载顺序

[第二次修改:linux中有各个模块init函数放在init断中。最先init的设备(驱动最先被注册),睡眠唤醒的时候最后被suspend最先被resume。]

 

需求:dsi这边的驱动需要比我一个挂载在i2c上的设备晚.

也就是说.平台端要先初始化i2c从设备以后,再输出mipi信号.

平台:qcom 8930

 做法

1.修改dsi

--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -3180,6 +3180,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
        static int te_irq_registered;
        struct mdss_panel_data *pdata;
+//    msleep(5000);
+//    mdelay(5000);
+    printk("mdss ctrl probe sleep 5s\n");
        if (!pdev || !pdev->dev.of_node) {
                pr_err("%s: pdev not found for DSI controller\n", __func__);
                return -ENODEV;
@@ -4357,6 +4358,7 @@ static int __init mdss_dsi_driver_init(void)
        return ret;
 }
 module_init(mdss_dsi_driver_init);
+//late_initcall(mdss_dsi_driver_init);
 
 
 static int mdss_dsi_ctrl_register_driver(void)
@@ -4377,6 +4379,7 @@ static int __init mdss_dsi_ctrl_driver_init(void)
        return ret;
 }
 module_init(mdss_dsi_ctrl_driver_init);
+//late_initcall(mdss_dsi_ctrl_driver_init);

msleep与mdelay都试过。不行。这个线程delay导致整个probe流程都不行。方法一失败

将module_init的逻辑改为late_initcall 。mdss_dsi这边确实会往后推。但是mdss逻辑probe太多。如果不全部往后推。系统panic挂掉。方法二也失败。

module_init的顺序其实如下

#define module_init(x)     __initcall(x);              //include\linux\init.h

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn)                 __define_initcall("6",fn,6)

#define __define_initcall(level,fn,id) \

         static initcall_t __initcall_##fn##id __used \

         __attribute__((__section__(".initcall" level ".init"))) = fn

[第一次更新:后来去试了一下,因为我们的从设备仅仅依赖gpio,i2c总线的初始化,其实我们可以使用rootfs_initcall即可将我们的i2c从设备的初始化顺序拉到mdss_dsi之前]

言归正传,INITCALLS在__initcall_start = .与__initcall_end = .之间,
表示INITCALLS宏内涵的相关段代码顺序存放在这里,module_init所代表段的镶嵌其中

#define pure_initcall(fn)          __define_initcall("0",fn,0)
#define core_initcall(fn)          __define_initcall("1",fn,1)
#define core_initcall_sync(fn)        __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)           __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn)          __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)        __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)              __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
#define fs_initcall(fn)                     __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)            __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)        __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)              __define_initcall("6",fn,6)
#define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
#define late_initcall(fn)           __define_initcall("7",fn,7)
#define late_initcall_sync(fn)         __define_initcall("7s",fn,7s)

MODULE是在kernel 根目录下面的makefile中定义的
KBUILD_AFLAGS_MODULE  := -DMODULE
KBUILD_CFLAGS_MODULE  := -DMODULE

因此如果在build module的时候会定义MODULE。而定了了MODULE的话,则下面的都是同一个优先级
#define early_initcall(fn)        module_init(fn)
#define core_initcall(fn)        module_init(fn)
#define core_initcall_sync(fn)        module_init(fn)
#define postcore_initcall(fn)        module_init(fn)
#define postcore_initcall_sync(fn)    module_init(fn)
#define arch_initcall(fn)        module_init(fn)
#define subsys_initcall(fn)        module_init(fn)
#define subsys_initcall_sync(fn)    module_init(fn)
#define fs_initcall(fn)            module_init(fn)
#define fs_initcall_sync(fn)        module_init(fn)
#define rootfs_initcall(fn)        module_init(fn)
#define device_initcall(fn)        module_init(fn)
#define device_initcall_sync(fn)    module_init(fn)
#define late_initcall(fn)        module_init(fn)
#define late_initcall_sync(fn)        module_init(fn)

#define console_initcall(fn)        module_init(fn)
#define security_initcall(fn)        module_init(fn)
--------------------- 
作者:tiantao2012 
来源:CSDN 
原文:https://blog.csdn.net/tiantao2012/article/details/54311085 
版权声明:本文为博主原创文章,转载请附上博文链接!

遍历相同优先级的initcall时,是按照地址从低到高进行的,因此调用顺序就是编译时连接到initcall section的顺序,通过System.map可以查到顺序,例如:

62054:ffffffc000e61c38 T __initcall_start

62055:ffffffc000e61c38 t __initcall_trace_init_flags_sys_exitearly

62057:ffffffc000e61c40 t __initcall_trace_init_flags_sys_enterearly

62058:ffffffc000e61c48 t __initcall_init_hw_perf_eventsearly

62059:ffffffc000e61c50 t __initcall_cpu_suspend_initearly

链接顺序可以通过调整Makefile中的.o文件的先后进行调整。

最后用的方法是:查看kernel_log 发现在kernel_log之前有一个i2c上的从设备probe成功了。

将我的驱动代码放在这个从设备的代码路径。make bootimage 烧录。解决

System.map,最终的probe结果以System.map为准,此文件在kernel的中间文件目录。

以后从我看到的情况来说。最早的probe顺序是放在pin脚的probe之后,毕竟这个时候驱动对外部的依赖基本满足.

System.map很重要,它可以告诉你目前系统kernel各个模块的加载顺序,如果你想更改顺序,可以依据这个信息去改动
[更上一层,现有kernel的加载顺序是单线程的,如果你觉得太慢,建议尝试在某一个level,比方说4开头创建线程去完成你自己的规划]

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常是因为你没有在初始化卷积层对象时提供必需的参数之一,即卷积核的大小 `kernel_size`。在初始化时,你需要指定卷积核的大小,例如 `nn.Conv2d(in_channels, out_channels, kernel_size)`。请确保你在初始化时提供了所有必需的参数。 例如,如果你的代码是这样的: ``` import torch.nn as nn class MyNet(nn.Module): def __init__(self): super(MyNet, self).__init__() self.conv1 = nn.Conv2d(3, 16) self.conv2 = nn.Conv2d(16, 32, kernel_size=3) self.fc1 = nn.Linear(32 * 6 * 6, 64) self.fc2 = nn.Linear(64, 10) def forward(self, x): x = self.conv1(x) x = nn.functional.relu(x) x = self.conv2(x) x = nn.functional.relu(x) x = nn.functional.max_pool2d(x, 2) x = x.view(-1, 32 * 6 * 6) x = self.fc1(x) x = nn.functional.relu(x) x = self.fc2(x) return x ``` 你需要将 `self.conv1 = nn.Conv2d(3, 16)` 改为 `self.conv1 = nn.Conv2d(3, 16, kernel_size=3)`,以指定卷积核的大小,例如: ``` import torch.nn as nn class MyNet(nn.Module): def __init__(self): super(MyNet, self).__init__() self.conv1 = nn.Conv2d(3, 16, kernel_size=3) self.conv2 = nn.Conv2d(16, 32, kernel_size=3) self.fc1 = nn.Linear(32 * 6 * 6, 64) self.fc2 = nn.Linear(64, 10) def forward(self, x): x = self.conv1(x) x = nn.functional.relu(x) x = self.conv2(x) x = nn.functional.relu(x) x = nn.functional.max_pool2d(x, 2) x = x.view(-1, 32 * 6 * 6) x = self.fc1(x) x = nn.functional.relu(x) x = self.fc2(x) return x ``` 这样就能够解决这个错误了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值