首页 > 其他分享 >uboot配置usbhost及代码初步分析--Apple的学习笔记

uboot配置usbhost及代码初步分析--Apple的学习笔记

时间:2023-10-23 22:32:29浏览次数:44  
标签:node usbhost run Apple cmd start ti uboot usb

一,前言

之前uboot没配置过usb,但是现在uboot基于DM模型基本和linux driver类似了。那么为了学习linux driver,我可以先学习uboot来做技术储备也是一样的。而且usb在uboot上应该也有用武之地,所以有必要进行刻意练习。

二,分析

1,之前对发现driver用了wraper的方式来打包进行绑定,我理解唯一的好处就是代码看起来更加模块化,在bind函数中对子node进行绑定driver。

U_BOOT_DRIVER(ti_musb_wrapper) = {
	.name	= "ti-musb-wrapper",
	.id	= UCLASS_MISC,
	.of_match = ti_musb_ids,
	.bind = ti_musb_wrapper_bind,
};

这样就算打印出来看起来有主模块和子模块,观察起来不至于分散。

misc          0  [   ]   ti-musb-wrapper       |   |-- usb@47400000
 usb           0  [   ]   ti-musb-host          |   |   `-- usb@47401800

但是我理解不用wrap单独处理也是可以的,所以我准备修改下ti-musb.c,改成不绑定而是独立的一个个,dtsi中已经有compatible参数了,我理解只要在c代码中添加一个个独立usb的of_match即可。然后把wrapper的注册删除掉。

2,结果按我思路usb驱动根本识别不了了,那么我猜测一定是父类没有match那么就不会再扫描子类了。 猜测父类没有匹配成功,就不会去扫描子类了。 所以再看看scan_node依次扫描是否有条件的,我先在此c文件中添加#define _DEBUG 1,看了打印的信息,我才知道原来就是昨天分析的。node去匹配所有的driver,找不到就continue,某个node全部的compatible都没有,继续向下if (entry->of_match)当然也不会有值,所以不对调用device_bind_with_driver_data,也就没有继续的归递下层子类了。

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;
       if (entry->of_match)
       {
           device_bind_with_driver_data
       }

打印的debug_info信息,No match和match的打印信息是不同的哦

bind node usb@47400000
   - attempt to match compatible string 'ti,am33xx-usb'
No match for node 'usb@47400000'
dm_scan_fdt_node node_name is:ethernet@4a100000
bind node ethernet@4a100000
   - attempt to match compatible string 'ti,am335x-cpsw'
   - found match at 'eth_cpsw': 'ti,cpsw' matches 'ti,am335x-cpsw'
Device '[email protected]' Driver 'eth_bootdev',drv->bind addr is 0x9ffbd9d1
dm_scan_fdt_node node_name is:sram@40300000
bind node sram@40300000
   - attempt to match compatible string 'mmio-sram'
No match for node 'sram@40300000'

3,知道无法匹配的根本原因,那么就好解决了,只要把设备树中的子节点提升为上层节点即可。可以用dm tree看到绑定成功了。

usb           0  [   ]   ti-musb-host          |   `-- usb@47401800

使用了下,也是正常的,同usb start,probe也成功。

AP-Boot=> usb start
starting USB...
Bus usb@47401800: Device 'usb@47401800' Driver 'ti-musb-host',drv->probe addr is 0x9ff9f11f
scanning bus usb@47401800 for devices... Device 'usb_mass_storage' Driver 'usb_mass_storage',drv->probe addr is 0x9ff7ea15
Device 'usb_mass_storage.lun0.bootdev' Driver 'usb_bootdev',drv->bind addr is 0x9ff9c41b
1 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found

4,问题来了,这个probe需要手工运行usb start的,那么我不调用usb start是否这驱动等于没用了,那么还加它干嘛呢? 于是我想着用qemu调试下vexpress_ca9x4_defconfig中的usb看看效果,接着它默认没有配置,我需要配置下,方法就是通过dts中的匹配信息搜索c代码,然后在makefile中找到这c文件需要的宏开关,添加了几个宏定义即可。

5,编译成功后,开始qemu仿真调试v9,在probe打断点,可以被调用,具体是通过环境变量中的usb命令start来probe的。路径如下

1	board_init_r
2	initcall_run_list
3	run_main_loop
4	main_loop
5	run_command_list
6	parse_string_outer
7	parse_stream_outer
8	run_list
9	run_list_real
10	run_pipe_real
11	cmd_process
12	cmd_call
13	do_run
14	parse_string_outer
15	parse_stream_outer
16	run_list
17	run_list_real
18	run_pipe_real
19	run_list_real
20	run_pipe_real
21	parse_string_outer
22	parse_stream_outer
23	run_list
24	run_list_real
25	run_pipe_real
26	cmd_process
27	cmd_call
28	do_run
29	parse_string_outer
30	parse_stream_outer
31	run_list
32	run_list_real
33	run_pipe_real
34	cmd_process
35	cmd_call
36	do_run
37	parse_string_outer
38	parse_stream_outer
39	run_list
40	run_list_real
41	run_pipe_real
42	cmd_process
43	cmd_call
44	do_usb
45	do_usb_start
46	usb_init
47	device_probe
48	isp1760_plat_probe

6,看了下感觉也是有归递的,cmd_call等都是重复的。最后怎么到了do_usb的命令呢!如图看到线索就是s为usb start,usb start好熟悉,不就是我之前手工输入的cmd命令呀~

uboot配置usbhost及代码初步分析--Apple的学习笔记_uboot

原来传入的参数是bootcmd,那么就能解释了。

const char *bootdelay_process(void)
{
	char *s;
	int bootdelay;
	bootcount_inc();
	s = env_get("bootdelay");
	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
	。。。。。。
	if (bootcount_error())
		s = env_get("altbootcmd");
	else
		s = env_get("bootcmd");
	return s;
}

7,稍微分析下代码流,cmd_process中主要调用find_cmd,接着调用cmd_call来执行命令 通过find_cmd_tbl在cmd表中找到命令,主要就是比较cmdtp->name

struct cmd_tbl *find_cmd(const char *cmd)
{
	struct cmd_tbl *start = ll_entry_start(struct cmd_tbl, cmd);
	const int len = ll_entry_count(struct cmd_tbl, cmd);
	return find_cmd_tbl(cmd, start, len);
}

另外看到归递parse_string_outer开始有重复,看到如下函数,用了归递调用parse_stream_outer。

int parse_string_outer(const char *s, int flag)
{
	struct in_str input;
	int rcode;
#ifdef __U_BOOT__
	char *p = NULL;
	if (!s)
		return 1;
	if (!*s)
		return 0;
	if (!(p = strchr(s, '\n')) || *++p) {
		p = xmalloc(strlen(s) + 2);
		strcpy(p, s);
		strcat(p, "\n");
		setup_string_in_str(&input, p);
		rcode = parse_stream_outer(&input, flag); //此行归递了。
		free(p);
		return rcode == -2 ? last_return_code : rcode;
	} else {
#endif
	setup_string_in_str(&input, s);  
	rcode = parse_stream_outer(&input, flag);
	return rcode == -2 ? last_return_code : rcode;
#ifdef __U_BOOT__
	}
#endif
}

8,但是这个bootcmd中的start usb是哪里来的呢?printenv先看看信息

=> printenv bootcmd
bootcmd=run distro_bootcmd; run bootflash
=> printenv distro_bootcmd
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
=> printenv boot_targets
boot_targets=mmc1 mmc0 pxe dhcp

我在do_run解析了arg参数后,添加了参数打印,断点依然在probe函数中,接着可以看到如下,参数包括boot_net_usb_start。

Net:   eth0: ethernet@3,02000000
Hit any key to stop autoboot:  0 
do_run:runcmd_arg is distro_bootcmd
do_run:runcmd_arg is bootcmd_mmc1
do_run:runcmd_arg is mmc_boot
MMC Device 1 not found
no mmc device at slot 1
do_run:runcmd_arg is bootcmd_mmc0
do_run:runcmd_arg is mmc_boot
Card did not respond to voltage select! : -110
do_run:runcmd_arg is bootcmd_pxe
do_run:runcmd_arg is boot_net_usb_start
starting USB...
Bus usb@3,03000000: 
......

在相关头3个头文件中找vexpress_ca9x4.h->vexpress_common.h->config_distro_bootcmd.h,在此h文件中能搜索到start usb。 BOOTENV_SHARED_USB什么时候调用的呢?

于是通过BOOTENV找到关键路径,env_default.h中有CFG_EXTRA_ENV_SETTINGS,这是开头,接着一路宏定义展开,就可以找到usb start了。 CFG_EXTRA_ENV_SETTINGS->BOOTENV->BOOTENV_SHARED_USB。

如下"run boot_net_usb_start就是run usb start。

#define BOOTENV_RUN_NET_USB_START "run boot_net_usb_start; "
#define BOOTENV_SHARED_USB \
	"boot_net_usb_start=usb start\0" \
	"usb_boot=" \
		"usb start; " \
		BOOTENV_SHARED_BLKDEV_BODY(usb)

我若不希望去调用usb probe函数从源头上只要BOOTENV_SHARED_USB设置为空,或者BOOTENV中不加入BOOTENV_SHARED_USB即可。其它相关的环境变量含义可以看doc文档doc/develop/distro.rst。

三,小结

没想到uboot中的设备树居然和linux driver中如此相似,那么通过uboot小巧的代码来学习设备树是一个不错的选择。

今天主要学习了关于wrap子类的用法,随意看了其它的usb驱动的c文件很多都用了wrapper的方式来写,wrapper的bind中,就直接把子类device和driver绑定了,主要调用device_bind_driver_to_node函数,例如如下就是判断设备树中的dr_mode模式属性,然后将此dev绑定到name为ti-musb-host的驱动。

case USB_DR_MODE_HOST:
            /* Bind MUSB host */
            ret = device_bind_driver_to_node(parent,"ti-musb-host",
            name,node,&dev);

标签:node,usbhost,run,Apple,cmd,start,ti,uboot,usb
From: https://blog.51cto.com/AppleCai/7994775

相关文章

  • qemu和vscode调试uboot及设备模型数据流分析
    一,前言对于通用的流程,我需要形成闭环的代码理解,验证我理解的准确性。于是我选择用调试的方法来看数据流,用qemu来仿真,vsocde来调试,但是不能仿真am335。所以用了qemu支持仿真的v9。二,过程记录1,编译ubootmakeARCH=armCROSS_COMPILE=arm-linux-gnueabihf-distcleanrm-rf./v9make......
  • Xcode 15.0.1 (15A507) 发布下载 - Apple 平台 IDE
    Xcode15.0.1(15A507)-Apple平台IDEIDEforiOS/iPadOS/macOS/watchOS/tvOS/visonOS请访问原文链接:https://sysin.org/blog/apple-xcode-15/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgvisonOS支持已更新。Xcode15使您能够为所有Apple平台开发、测......
  • uboot为LED添加DM驱动--Apple的学习笔记
    一,前言开始玩所有板子一般都是先点灯,比如我可以在汇编中点灯,可以在board_init中用writel写寄存器点灯,当我要进一步熟悉下设备树驱动模型,不管学习linux还是学习uboot这块我理解类似,所以我要通过添加设备树及配置开关来实现默认打开led0和led1的功能。二,实现的过程1,先有了dts信息,我从......
  • 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......
  • Apple macOS Sonoma All In One
    ApplemacOSSonomaAllInOneMBP2018✅/Macmini2018✅macOSSonomafeaturesHRD240FPS慢动作视频壁纸https://www.apple.com/macos/sonoma/https://www.apple.com/macos/sonoma/pdf/macOS_All_New_Features.PDFdemos(......
  • 海外apple 登陆 快速配置 Sign In with Apple
    登录Apple开发者账号。我们需要获得具有SignInwithApple功能的AppId。•进入Certificates,Identifiers&Profiles>Identifiers,然后单击Identifiers旁边左上角的+号;•选择AppIDs并点击继续; 在此处输入任意Description和BundleID(Apple建议使用反......
  • boot驱动模型中的常用API--Apple的学习笔记
    一,前言之前解决ping问题的过程中,需要看uboot的代码,感觉看起来很轻松,我一直觉得代码写的小学生都能看懂的,这才是高手写的代码。面向对象设计的好,封装做的也好。虽然和qemu的Qobject设计雷同,但是我又手痒想画图了。二,学习1,uclass_find(id)根据uclassid来找uclass。在gd->uclass_roo......
  • 解决uboot ping不通的硬件问题--Apple的学习笔记
    一,前言之前uboot偶尔第一次上电会ping通一次,之后就ping不通,我以为电源问题,好像也不是,然后我又认为是交叉网线问题,我用的可能是直连网线,之前用的交叉网线头子坏了我就丢了。于是网上买了新的交叉网线,到货后依然ping不通,而且一次都不行了。难道代码有问题,于是用了我之前的uboot代码,结......
  • Apple 推出全球开发者资源 —— 人人能编程
    近日,Apple宣布推出MeetwithAppleExperts开发者资源,帮助全球Apple开发者社区发现并参与课程、研讨会、实验室、一对一咨询等体验。MeetwithAppleExperts初期提供超过50个课程、研讨会和咨询项目,并将持续提供线上和线下活动,开发者也可借助该平台和Apple专家......