当前位置: 首页 > news >正文

移植firefly core-1126-jd4官方sdk源码到其他rv1126板卡时 kernel启动中失去响应问题解决

问题背景

在项目中采用firefly core-1126-jd4的sdk适配其他rv1126板卡遇到kernel启动中无响应。串口能看到运行到usb、mmc等模块驱动流程,但之后就打印,通过追加打印确认usb、mmc模块的init已经执行完,怀疑是执行其他某个静态编译进kernel的模块init中失去响应,但该模块失去响应前并未有任何打印,所以不确定具体是哪个模块。茫茫kernel数百上千个模块难以分析。

问题定位

kernel源码的init/main.c文件中有个二维函数地址表initcall_levels,定义如下:

extern initcall_entry_t __initcall_start[];
extern initcall_entry_t __initcall0_start[];
extern initcall_entry_t __initcall1_start[];
extern initcall_entry_t __initcall2_start[];
extern initcall_entry_t __initcall3_start[];
extern initcall_entry_t __initcall4_start[];
extern initcall_entry_t __initcall5_start[];
extern initcall_entry_t __initcall6_start[];
extern initcall_entry_t __initcall7_start[];
extern initcall_entry_t __initcall_end[];
static initcall_entry_t *initcall_levels[] __initdata = {__initcall0_start,__initcall1_start,__initcall2_start,__initcall3_start,__initcall4_start,__initcall5_start,__initcall6_start,__initcall7_start,__initcall_end,
};
static char *initcall_level_names[] __initdata = {"pure","core","postcore","arch","subsys","fs","device","late",
};

一级索引表示等级,二级地址表示各个等级内模块的数组,二级数组中每一项都是链接脚本中的一个内存段,各个数组与内存段的对应关系如下:
__initcall_start --> .initcallearly.init
__initcall0_start --> .initcall0.init
__initcall1_start --> .initcall1.init
__initcall2_start --> .initcall2.init
__initcall3_start --> .initcall3.init
__initcall4_start --> .initcall4.init
__initcall5_start --> .initcall5.init
__initcall6_start --> .initcall6.init
__initcall7_start --> .initcall7.init
__initcall_end --> .con_initcall.init
各个段都有一系列module的init函数。
kernel在kernel_init中会根据该二维表逐个调用各层级各模块的init函数以加载各模块。
有个do_initcalls会do_initcall_level函数
kernel_init
---->kernel_init_freeable
-------->do_pre_smp_initcalls (遍历加载.initcallearly.init中的模块)
-------->do_basic_setup
---------------->do_initcalls (遍历加载.initcall0.init~.initcall7.init各内存段中的各模块)
-------------------------------->do_initcall_level (遍历加载具体内存段中的各模块)xs
其中do_initcall_level 实现如下(加入追踪打印):

static void __init do_initcall_level(int level)
{// 忽略无关逻辑for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) {printk("aaaa %pF\n",initcall_from_entry(fn));do_one_initcall(initcall_from_entry(fn));printk("bbbb\n");}
}

内核中除了极个别早期模块会在do_pre_smp_initcalls中加载,大多数模块在do_initcall_level中加载。
根据打印在aaaa mdev_misc_init之后并没有bbbb打印,确认内核在mdev_misc模块中失去响应。
然而grep搜遍内核并未见mdev_misc模块在哪里实现,反而是在vmlinux及mmc_blk_data两个二进制文件中有mdev_misc_init字符串,通过file确认mmc_blk_data是firefly通过ar打包多个.o文件的集合静态库。
kernel/drivers/mmc/core/Makefile中有如下片段:

obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
mmc_block-objs			:= block.o queue.o
mmc_block-objs          += mmc_blk_data

其中mmc_block.o及mmc_block-objs并非真实的编译单元文件及编译目标规则,只是一种目标依赖传导规则,表示通过obj-$(CONFIG_MMC_BLOCK)加入mmc_block.o目标,而mmc_block-objs表示mmc_block.o并不从mmc_block.c文件编译而来,而是关联到block.o queue.o mmc_blk_data三个文件,其中block.o queue.o分别是各自c源码编译而来,mmc_blk_data为预置静态库,不提供源码。
追踪代码确定block.c中调用的mmc_blk_data中实现的mmc_blk_data_init与mmc_blk_data_deinit两个函数。
修改如下:

// #include "block_data.h" 取消该头文件引用
// 忽略无关逻辑
if (card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) {// mmc_blk_data_init(md); 注掉对mmc_blk_data_init调用
}
// 忽略无关逻辑
if (card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) {// mmc_blk_data_deinit(md); 注掉对mmc_blk_data_deinit调用
}

再次编译kernel烧写即可运行通过。

相关文章:

  • 2025年特种设备安全管理 A 证考试全解析
  • 力扣 797. 所有可能的路径
  • 2025宽带避坑指南:百兆、千兆、万兆到底怎么选
  • 对话框类别组件编写
  • 【开源项目】Excel手撕AI算法深入理解(四):注意力机制(Self-Attention、Multi-head Attention)
  • HashMap中put方法的执行流程
  • IOS微信小程序无法显示背景图片
  • 音频识别优化(FFT)
  • 认识Vue
  • Java锁的分类与解析
  • QT6 源(34):随机数生成器类 QRandomGenerator 的源码阅读
  • 科学护理进行性核上性麻痹,缓解病痛提升生活质量
  • 用cython将python程序打包成C++动态库(windows+Vistual Studio2017平台)
  • Lombok @Builder 注解的进阶玩法:自定义 Getter/Setter 方法全攻略
  • 在没有第三方库的情况下使用 Python 自带函数解码
  • 3.串口通信之SPI
  • Java学习手册:Java内存模型
  • 22、字节与字符的概念以及二者有什么区别?
  • 【Python爬虫基础篇】--1.基础概念
  • MCP Server和Client的基本使用方法
  • 四川省社科联期刊:不建议在读硕士、博士将导师挂名为第一作者
  • 国家发改委:我国能源进口来源多元,企业减少甚至停止自美能源进口对国内能源供应没有影响
  • 人社部:将会同更多部门分行业、分领域制定专项培训计划
  • 明查|把太平洋垃圾污染问题甩锅中国,特朗普用的是P过的图
  • 最大规模的陈逸飞大展启幕:回望他,回望一个时代
  • 双拥主题歌曲MV:爱我人民,爱我军