首页 > 其他分享 >qemu和vscode调试uboot及设备模型数据流分析

qemu和vscode调试uboot及设备模型数据流分析

时间:2023-10-22 18:31:31浏览次数:26  
标签:node core uboot vscode bind drivers device qemu arm

一,前言

对于通用的流程,我需要形成闭环的代码理解,验证我理解的准确性。于是我选择用调试的方法来看数据流,用qemu来仿真,vsocde来调试,但是不能仿真am335。所以用了qemu支持仿真的v9。

二,过程记录

1,编译uboot

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
rm -rf ./v9
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=v9 vexpress_ca9x4_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=v9

2,编译qemu的arm版本,进入qemu目录

mkdir build && cd build
../configure --target-list=arm-softmmu --audio-drv-list= --enable-debug
make

3,仿真uboot 前提

export PATH=/work/tools/qemu-2.8.0/build/arm-softmmu:$PATH

进入路径/work/v9/u-boot-2023.10/v9,输入命令仿真uboot的命令

qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M

qemu退出仿真的方法:先按ctrl+a,然后松口按一个x。

4,通过gdb调试qemu开发板 前提

export PATH=/work/tools/qemu-2.8.0/build/arm-softmmu:$PATH

进入uboot文件所在目录,通过启动参数来启动gdb server

qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M --gdb tcp::1234 -S

Client

arm-linux-gnueabihf-gdb /work/v9/u-boot-2023.10/v9/u-boot
然后输入
target remote localhost:1234

5,通过vscode调试qemu开发板 前提

export PATH=/work/tools/qemu-2.8.0/build/arm-softmmu:$PATH

进入uboot文件所在目录,通过启动参数来启动gdb server

qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M --gdb tcp::1234 -S

客户端创建.vscode文件夹再创建launch.json文件,最后按F5运行客户端调试即可。

{
    "version":"0.2.0",
    "configurations":[
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "/work/v9/u-boot-2023.10/v9/u-boot",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "miDebuggerPath": "/work/tools/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gdb",
            "miDebuggerServerAddress":"localhost:1234",
            /*"preLaunchTask":"build",*/
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

6,uboot中会重新搬运,所以符号表就会不匹配,若要打断点就不起作用了。需要调试搬运后的代码,就需用在gdb中重新加载符号表。这个重定向地址编译后会变化的

-exec b relocate_code   //进入此断点后,就可以重新加载uboot了
-exec add-symbol-file /work/v9/u-boot-2023.10/v9/u-boot 0x7ff60000 //重新加载后,则可打正常断点了
-exec b board_init_r

qemu和vscode调试uboot及设备模型数据流分析_vscode调试

7,关于bind路径 我调试的设备对象为mmc,bind的路径

board_init_r(\common\board_r.c:818)
initcall_run_list(\include\initcall.h:46)
dm_init_and_scan(\drivers\core\root.c:433)
dm_scan(\drivers\core\root.c:409)
dm_extended_scan(\drivers\core\root.c:330)
dm_scan_fdt(\drivers\core\root.c:309)
dm_scan_fdt_node(\drivers\core\root.c:288) ----1
lists_bind_fdt(\drivers\core\lists.c:253)
device_bind_with_driver_data(\drivers\core\device.c:244)
device_bind_common(\drivers\core\device.c:178)
simple_bus_post_bind(\drivers\core\simple-bus.c:57)
dm_scan_fdt_node(\drivers\core\root.c:288) ----2
lists_bind_fdt(\drivers\core\lists.c:253)
device_bind_with_driver_data(\drivers\core\device.c:244)
device_bind_common(\drivers\core\device.c:178)
simple_bus_post_bind(\drivers\core\simple-bus.c:57)
dm_scan_fdt_node(\drivers\core\root.c:288) ----3
lists_bind_fdt(\drivers\core\lists.c:253)
device_bind_with_driver_data(\drivers\core\device.c:244)
device_bind_common(\drivers\core\device.c:178)
simple_bus_post_bind(\drivers\core\simple-bus.c:57)
dm_scan_fdt_node(\drivers\core\root.c:288) ----4
lists_bind_fdt(\drivers\core\lists.c:253)
device_bind_with_driver_data(\drivers\core\device.c:244)
device_bind_common(\drivers\core\device.c:168)
arm_pl180_mmc_bind(\drivers\mmc\arm_pl180_mmci.c:499)

lists_bind_fdt是匹配的关键函数,首先在driver中遍历,然后和node的compatible字段进行比较

for (i = 0; i < compat_length; i += strlen(compat) + 1) {
        ...
        
        id = NULL;
        for (entry = driver; entry != driver + n_ents; entry++) {
            if (drv) {
                if (drv != entry)
                    continue;
                if (!entry->of_match)
                    break;
            }
            ret = driver_check_compatible(entry->of_match, &id, compat);
            if (!ret)
                break;
        }
        if (entry == driver + n_ents)
            continue;  
        ...

        ret = device_bind_with_driver_data(parent, entry, name,
                           id ? id->data : 0, node,
                           &dev);
         ...                    
    }

比较是通过driver_check_compatible函数,若strcmp为0说明找到了,然后返回0,就break,退出driver的遍历了。若driver全部扫描完了还没找到,最后退出时候判断entry等于最后一个driver,那么就continue,不会向下再走到device_bind_with_driver_data了,重新开始循环compat_length的node字符串内容。否则会进入device_bind_common来创建device设备且绑定driver。

static int driver_check_compatible(const struct udevice_id *of_match,
                   const struct udevice_id **of_idp,
                   const char *compat)
{
    if (!of_match)
        return -ENOENT;

    while (of_match->compatible) {
        if (!strcmp(of_match->compatible, compat)) {
            *of_idp = of_match;
            return 0;
        }
        of_match++;
    }
    return -ENOENT;
}

我由于是打断点进行子类bind函数,所以父类都是compatible mach的。所以会看到4个相同的调用路径。 分析主要函数,发现dm_scan_fdt_node会被重复调用4次后进入bind函数,原因是node的父类和子类关系图可以看出node mmc在第4层。

smb@4000000
	motherboard
		iofpga@7,00000000
			mmci@5000

dm_scan_fdt_node主要就是在父类node中从第一个子类node开始扫描,所以第一个scan的node是smb对象,然后是motherboard依次遍历扫描到了mmci@5000进行了bind调用。

for (node = ofnode_first_subnode(parent_node);
         ofnode_valid(node);
         node = ofnode_next_subnode(node)) {
        const char *node_name = ofnode_get_name(node);
......
        err = lists_bind_fdt(parent, node, NULL, NULL, pre_reloc_only);
......
    }

只要是UCLASS_SIMPLE_BUS类的,没有bind函数,但是都有post_bind

UCLASS_DRIVER(simple_bus) = {
    .id     = UCLASS_SIMPLE_BUS,
    .name       = "simple_bus",
    .post_bind  = simple_bus_post_bind,
    .per_device_plat_auto   = sizeof(struct simple_bus_plat),
};

而post_bind的函数simple_bus_post_bind主要就是继续遍历下层node进行驱动绑定,调用的函数依然是dm_scan_fdt_node,所以看上去像是归递的效果来寻找子类。

static int simple_bus_post_bind(struct udevice *dev)
{
	return dm_scan_fdt_dev(dev);
}
int dm_scan_fdt_dev(struct udevice *dev)
{
    return dm_scan_fdt_node(dev, dev_ofnode(dev),gd->flags & GD_FLG_RELOC ? false : true);
}

8,关于probe的流程 这个看起来比较少,扫描uclass中的device,通过seq来匹配。device_probe完成后设置DM_FLAG_ACTIVATED标志,device_probe先会处理父类设备进行probe,device_probe(dev->parent)。然后才是自己probe,ret = drv->probe(dev)。probe就是真正的通过driver来初始化设备了。

board_init_r
initcall_run_list
initr_mmc
mmc_initialize
mmc_probe
uclass_get_device_by_seq
uclass_get_device_tail
device_probe
arm_pl180_mmc_probe

三,小结

本次主要学习了gdb的symbol文件加载命令,深入学习了基于dm的数据流,这样等于形成一个代码理解的闭环,之前我看着就点乱,感觉会重复probe,原来有DM_FLAG_ACTIVATED标志。之前node的遍历方式不太清楚,现在知道是先按node来遍历compatible,然后在driver list中搜进行字符串匹配,至于匹配后就会创建device对象,然后调用prebind,bind,postbind这类钩子函数。而probe是初始化device当然要在bind后面,而且probe先进行父类设备再进行子类设备。今天看的这个system_bus的回调函数,学习到一招,就是post_bind的用途,这样可以看出bus和mmc虽然都匹配了,但是后面调用的路径不同。通过system_bus还形成了post_bind的子node归递查询,非常棒的设计。

标签:node,core,uboot,vscode,bind,drivers,device,qemu,arm
From: https://blog.51cto.com/AppleCai/7978205

相关文章

  • VSCode配置Clang C/C++开发环境 [+clangd代码静态检查配置]
    问题:gcc/g++是c/c++使用最广泛的编译器,也是linux默认自带的编译套件,但在vscode上,也可通过微软官方提供的C/C++插件很便捷进行c/c++代码编译调试,但是该插件的自动补全和代码提示等功能很差,经常给不出合理的候选项。另外一套C/C++代码编译套件是基于LLVM的clang/clang++编译器、ll......
  • uboot为LED添加DM驱动--Apple的学习笔记
    一,前言开始玩所有板子一般都是先点灯,比如我可以在汇编中点灯,可以在board_init中用writel写寄存器点灯,当我要进一步熟悉下设备树驱动模型,不管学习linux还是学习uboot这块我理解类似,所以我要通过添加设备树及配置开关来实现默认打开led0和led1的功能。二,实现的过程1,先有了dts信息,我从......
  • vscode 配置 ssh登录
    先在本地windows环境下安装好ssh,然后用ssh-keygen-trsa-C"[email protected]"生成密钥在服务器上也使用ssh-keygen-trsa-C"[email protected]"生成密钥将本地的公钥传递到服务器:scp.\[email protected]:~在.ssh文件夹创建authorized_keys:touch~/.ssh/aut......
  • uboot/Linux下MMC/SD/SDIO阅读记录
    1uboot下MMC/SD/SDIO1.1uboot下MMC/SD/SDIO相关配置uboot下关于MMC/SD/SDIO驱动以及工具配置:DeviceDrivers->MMCHostcontrollerSupportMMC/SD/SDIOcardsupport supportforMMC/SDwriteoperations--支持对MMC/SD/SDCar......
  • uboot定制自己的板子--Apple的学习笔记
    一,前言既然下载了最新的uboot版本,那么就玩玩吧,先要定制自己的板子。二,问题分析及解决1,出错信息U-BootSPL2023.10(Oct192023-19:58:50+0800)TryingtobootfromMMC1U-Boot2023.10(Oct192023-19:58:50+0800)AppleCai'sam335BoardCPU:AM335X-GPrev2.1......
  • VsCode 配置-新手
    保存时自动保存代码保存时自动删除无关引用打开settings.json后加入"editor.codeActionsOnSave":{"source.organizeImports":true},保存时自动删除缓存按下ctrl+shift+p,出现以下视图,并输入CleanJavalanguageserverworkspace此时会有弹出,然后选择Reloadan......
  • [转] VSCode中 Vetur插件排版Vue文件 Col 标签子标签不被缩进的问题 iview viewDesign
    [转]VSCode中Vetur插件排版Vue文件Col标签子标签不被缩进的问题iviewviewDesign自动格式化问题Col标签不对齐首先直接放解决办法在vsCodesettings.json中添加{//缩进大小,自行按需配置"vetur.format.options.tabSize":4,"vetur.format.defaultFo......
  • flutter vscode iOS app debug 出错 记录1
    出现类似错误Error(Xcode):Targetdebug_unpack_iosfailed:Exception:Failedtocodesign/Users/cappuccino/Desktop/develop/code/app1/flutter_application_1/build/ios/Debug-iphonesimulator/Flutter.framework/Flutterwithidentity-.这个是由于代码所在文件夹被iC......
  • vscode 上无法 prettier 加载配置文件失败的问题
    1.prettier的配置文件有几种格式,先按照官方文档 配置好2.如果想按住Ctrl+Alt+L格式化代码,需要关闭vscode中的formatOnSave3.每次修改完设置需要重启vscode,这里重启的正确步骤:File->CloseFolder,再重新打开项目注意:不要直接关闭vscode窗口,这样重新打开vscod......
  • vscode远程ubuntu,python不识别opencv的函数
    将opencv-python更新到4.8版本以上https://github.com/microsoft/pylance-release/issues/4838......