背景说明

去年下半年时间较多,每天下班了总得找点事干,之后偶尔看到XR872这款芯片,感觉可玩性还比较高,蓝牙WIFI、PSRAM、CSI编解码应有尽有,本着玩一玩的心态,计划是要将最新的uboot和linux移植上去的(据说uClinux已经融入linux主线,支持NOMMU了,所以也想验证一下)。但是后来由于干其他的事去了,uboot的移植已经搁浅差不多半年了,所以现在把我移植的代码分享出来,给后边喜欢折腾的朋友提供一个参考。

目前移植的u-boot已经可以入命令行,启动后开发板指示灯亮起,可正常使用loadx和go命令跑裸板程序了。

这是之前发的几篇文章,为本篇做铺垫:

XR872 打包自定义镜像与烧录https://blog.csdn.net/qq_28824733/article/details/124436295XR872 官方bootloader程序分析https://blog.csdn.net/qq_28824733/article/details/124436820XR872 自打包的镜像烧录出现Verify boot error解决办法https://blog.csdn.net/qq_28824733/article/details/124438272

环境说明

编译系统:Ubuntu

uboot蓝本:u-boot-v2021.07.tar.gz

交叉工具链:gcc-arm-none-eabi-10.3-2021.07-x86_64-linux.tar.bz2

我的代码仓库:https://gitee.com/huxiangjs/u-boot-v2021.07

测试开发板:

编译步骤

(1)克隆工程源码

git clone https://gitee.com/huxiangjs/u-boot-v2021.07.git

(2)编译命令

cd u-boot-v2021.07
make xr872_defconfig O=../build_xr872
make CROSS_COMPILE=../../arm-gcc/gcc-arm-none-eabi-10.3-2021.07/bin/arm-none-eabi- ARCH=arm O=../build_xr872

(3)制作烧录镜像

./mkimage

关于这个工具的说明请看我之前发表的铺垫文章,目前我的image.cfg文件内容为:

{"magic" : "AWIH","version" : "0.4","OTA" : {"addr": "1024K", "size": "4K"},"image" : {"max_size": "1020K"},"count" : 1,"section" :[{"id": "0xa5ff5a00", "bin": "../build_xr872/u-boot.bin", "cert": "null", "flash_offs": "0K", "sram_offs": "0x00200000", "ep": "0x002003fc", "attr": "0x1"},{}]
}

如上步骤是正确的,最终会得到xr_system.img文件,烧录到开发板即可。

UBOOT实际测试

(1)启动之后

(2)help命令

(3)loadx命令(传入了一个uart裸板测试程序)

(4)go命令

程序已经正常跑起来了。

后面附上调试的一些记录,如有错误请指出,3Q

UBOOT分析及调试记录

首先分析UBOOT, 以stm32f429分析为例。

分析要点:

  1. 看uboot的uboot.lds,可以知道代码如何分布。
  2. 看目录下生成的.o文件,可以知道哪些源码被编译过。

先用stm32的默认配置编译一下(生成.o文件):

make stm32f429-discovery_defconfig

make menuconfig

make CROSS_COMPILE=../gcc-arm-none-eabi-10.3-2021.07/bin/arm-none-eabi- ARCH=arm

或者指定目录:

make stm32f429-discovery_defconfig O=../build

make menuconfig O=../build

make CROSS_COMPILE=../../arm-gcc/gcc-arm-none-eabi-10.3-2021.07/bin/arm-none-eabi- ARCH=arm O=../build -j8

uboot.lds中得到代码组织顺序:

搜索这个字段在哪儿:

u-boot-v2021.07/arch/arm$ grep -rn vectors

找到结果(带m的,因为是Cortex-M系列,而且目录下有vectors_m.o表示编译过):

内容如下:

分析下一块,也就是start.o的源码start.S,文件再u-boot-v2021.07/arch/arm/cpu/armv7m/start.S,其中reset这个就是在上边中断向量表中指定的。

查找这个_main在哪里:

u-boot-v2021.07/arch/arm$ grep -rn _main

找到:

分析crt0.S文件,crt为C runtime environment的缩写,也就是c运行环境。看看_main处的入口代码:

寻找board_init_f函数:

u-boot-v2021.07/common$ grep -rn board_init_f

发现:

分析这个函数内容:

也就是把这个函数指针数组里的代码都调用一遍:

顺着代码,开始移植。首先建立配置文件:

接接下来就要编写这个文件了,要知道如何写,就要分析Makefile函数,首先看uboot根目录下的Makefile文件,看看我们传进去的ARCH=arm参数干嘛用了:

所以重点就在arch/arm/Makefile下,分析一下这个文件。

所以在目录下新建xr872:

xr872_defconfig中增加:

重新defconfig,提示代码段地址无效:

那就设置一个,这个地址不一定对,后边根据需要调整:

至此,defconfig已经没有问题了,但是编译会有问题。

编译提示的错误:

代码如下:

检查.config,发现CONFIG_ARM64被默认打开了:

好吧,看来是有地方还需要增加。首先对Kconfig增加芯片选项吧,加入:

这里可以通过select CPU_V7M来选择指令集,所以可以把xr872_defconfig中的那一行去掉了。此时不出意外,menuconfig中就可以找到这个选项了:

此时再检查生成的.config文件中,CONFIG_ARM64已经没有了。

再次编译,报错:

查看这个文件(注意这个是在指定的编译目录下):

发现在这个目录有很多config文件:

依葫芦画瓢,建一个我们的config文件:touch xr872.h,编译一下,还是有问题,那说明不是这个问题,那就借鉴一下stm32的看看:

原来,板级文件夹还没有创建呢。但是这个路径CONFIG_BOARDDIR是如何确定的呢,看看构建的文件:

参考stm32,原来在这而定义的:

它被这个文件包含:

而这个文件又被这个文件包含:

所以最终还是被mach-*下的Kconfig文件控制着。那就继续画瓢,创建这些内容。

而mach-*下的Kconfig文件是在arm文件夹下的Kconfig中包含。

arm文件夹则就是我们make时候ARCH=arm所指定的,所以层层控制。

依葫芦画瓢完,再次编译,之前的问题已经没有了,这时候应该制作Makefile文件了:

提示板级Makefile错误:

直接上面的Makefile拷贝一个即可。

新问题:

依葫芦画瓢添加(这个地址后续调整,目前只要求编译通过):

如下问题,也这么解决,可以参考其它芯片的配置。

再次编译,还有错,是因为我们还没有创建源文件呢:

添加(文件内容置空就OK):

再次编译,编译阶段已经没有问题了,链接出错,因为有些函数还没有实现:

研究代码,发现如果要调用print_cpuinfo是需要打开CONFIG_DISPLAY_CPUINFO宏的,默认是打开,所以我们关闭它:

解决dram_init未实现,首先看出错的地方:

发现没有宏来控制,那就实现一下这个函数把:

文件头很漂亮,因为是VScode自动生成的。

board_init问题,看源码:

要使这些宏都为0才可以保证不调用这个函数,但是这个CONFIG_ARM肯定是需要被配置的,所以就实现这个函数吧:

cread_line问题,看源码:

默认是打开的:

那就关掉它(后续需要时打开):

接下来就到了串口问题:

那就实现一下这个函数(内容以后再实现):

接下来就是滴答时钟的问题:

实现一下这个函数:

编译成功:

之后加入led函数:

加进init_sequence_f中:

led此时已经可以点亮了,说明程序可以运行到这里面了。

把led_on移动到init_sequence_f尾部,发现不能点亮,那说明这中间有函数出问题了。

测试发现是在serial_init中卡死的,这个是因为之前那个default_serial_console函数中,直接返回了个NULL指针,估计这个函数是被serial_init调用了,所以出错,看代码,果然:

好吧,那就先把串口实现了!

实现完后,串口已经有输出了,但是肯定卡在哪个地方了:

通过led的指示,发现在这个函数卡死了:

看来是重定位代码出问题了,先把debug打开:

再次启动,有很多调试信息输出了:

分析上面的log,明显可以看出来有些地址是不对的:

新栈指针都设置错了,那肯定有问题:

好,那就分析一下看看代码是如何重定位relocation代码的:

预留的空间直接是从栈空间里减掉。

上面代码中,r9原先保存了gd所在的地址,之后做了一个操作,把r9切换到了new_gd所在位置。下边来分析一下relocate_code是如何实现的:

那么现在可以得出如下结论:

(1)保证gd->new_gd ->reloc_off等于0,这样返回地址就是目前here的地方。

(2)保证gd->new_gd ->relocaddr等于__image_copy_start。

确保这俩个条件无误,应该就可以跳过代码重定向了。

看看gd->new_gd是如何被设置的:

通过如上分析,可以知道,只要把ram_base设置为适当的位置,就可以跳过代码重定向,但是,为啥要gd->relocaddr = gd->ram_top呢?往后看就知道:

那么新分配的new_gd又是如何初始化的呢:

综合上述,可以知道只需要做gd->ram_base和gd->ram_size的初始化,uboot就可以正常跑起来,那就再dram_init中做吧:

果然跑起来的,进入可控制台,把DEBUG关掉后效果如下:

目前串口的输入还没实现,看一下这几个函数的功能:

顺着代码跳转,看看uboot的读取机制:

实现后效果:

发现控制台不好看,=>符合前少了些什么,同分析发现可通过如下来定义:

效果如下:

另外发现按上下键没有出现命令历史记录,这是由于前面在defconfig中把CONFIG_CMDLINE_EDITING关闭掉了,而这个宏控制了这个功能:

那就删除掉这一句:

# CONFIG_CMDLINE_EDITING is not set

再次编译, 发现卡死了,那这个问题暂时不解决吧,毕竟RAM有限:

目前loadx命令还不能用,卡在第一个C位置:

分析代码,发现每次接受超时会有个延时操作:

而可以看到这个延时和滴答时钟有关系:

之后发现了我们之前实现的一个函数,这个函数直接返回了0,这是一个滴答时钟与微秒的比例系数:

而滴答时钟的初始化在这里:

用命令看一看,发现滴答时钟没有运行:

经过研究发现,uboot在进入loadx后会每隔一段时间发送一个C字符,电脑在收到这个C字符后开始传输数据,目前就是卡在第一个C字符,后面就不会有C字符输出,原因在这里:

看一看get_timer的代码:

看看这个timer_read_counter函数:

所以实现一下试试:

这个时候C可以一个一个出现,传输数据也没有问题了:

当然这只是个实验,还是要想办法把滴答时钟打开!

接下来要启用滴答时钟:

经过研究发现,armv7m/systick-timer.c受一个宏控制:

所以在xr872_defconfig中可以把这个宏设置为y,再次编译,发现还以没有编译systick-timer.c这个文件,之后通过menuconfig发现它还依赖ARM64或者ARMV7A,之后我在把ARMV7A也值为y,发现也没有编译这个问题。(连.config中都没出现CONFIG_SYS_ARCH_TIMER这个宏)。

所以直接粗暴简单:

还发现一个问题是,之前在xr872_defconfig中配置的CONFIG_TIMER=y,也没有在.config文件中找到,所以属于无效配置,在menuconfig中看看,发现确实有依赖:

依赖DM,所以暂时不处理,直接CONFIG_TIMER=y也注释掉。

再次编译,发现提示get_tbclk多重定义,这时候回到soc.c中,去掉我们之前加的那个get_tbclk函数,再次编译,成功。

启动uboot是没有问题的,但是使用loadx就直接挂了:

经过调试,发现问题,原因是因为0除以0出现问题。这个get_ticks()获取到的值为0,而gd->arch.timer_rate_hz也为0

这里应该要根据手册,把滴答时钟的时钟源打开,手册上已经找到了。滴答时钟源有俩种,低速和高速,当使用高速时钟,也就是cpu的时钟,这时候就不需要配置其它寄存器了,因为这个时钟直接从cpu引过来了,所以这里不再配置其它寄存器,直接使用cpu时钟了。

指定CPU频率:

之后loadx就已经可以使用了。

优化一下直接简单粗暴, 修改Kconfig:

恢复原状:

再次编译,OK

==============

实现历史命令选择:

设置CONFIG_CMDLINE_EDITING=y

发现启动后卡死,现在log.h中把DEBUG打开

发现只要调用mem_malloc_init就卡死,通过直接读取mem_malloc_init所在地址的数据发现,这个函数的代码竟然没被拷贝过去,难道是拷贝达到极限了?待后续确定

需要缩减u-boot.bin的尺寸,首先,分析每一个built-in.o文件大小,

发现网络占了比较大的空间,所以首先关掉网络:

重新编译后,xr_system.img大小从107KB减少到了85.3 KB

这时候再开启CONFIG_CMDLINE_EDITING=y

编译后的xr_system.img大小为:86.8 KB,再次启动,问题解决,功能正常!

历史命令也是可以切换了!这样验证了前面所说的“拷贝达到极限”的猜测。

XR872 移植 u-boot-v2021.07相关推荐

  1. 电脑公司win11旗舰版32位镜像v2021.07

    电脑公司win11旗舰版32位镜像v2021.07是一款非常好用的电脑操作系统,系统中的功能较为全面,且充满了独具的特色,让你可以快速的将系统完成安装,而且不用激活,安装完成就能立即使用,大大节省用户 ...

  2. 系统之家win11旗舰版32位镜像v2021.07

    系统之家win11旗舰版32位镜像v2021.07是一款非常好用的电脑操作系统,系统中的功能较为全面,且充满了独具的特色,让你可以快速的将系统完成安装,而且不用激活,安装完成就能立即使用,大大节省用户 ...

  3. 深度技术win11 32位全新专业版系统v2021.07

    深度技术win11 32位全新专业版系统v2021.07是一款有着多种安装方式可供用户们选择的装机系统,系统优化清理,空间纯使用,无任何垃圾,优化系统运行环境,不影响稳定性,自动安装最新官方驱动,充分 ...

  4. 番茄花园win11 32位专业版镜像系统v2021.07

    番茄花园win11 32位专业版镜像系统v2021.07是一款有着多种安装方式可供用户们选择的装机系统,系统优化清理,空间纯使用,无任何垃圾,优化系统运行环境,不影响稳定性,自动安装最新官方驱动,充分 ...

  5. 中关村windows11 32位专业版镜像v2021.07

    中关村windows11 32位专业版镜像v2021.07是一款精心设计过的优秀装机系统,支持多种安装方式,系统中的服务项.注册表等,都是经过全面优化,能够很好的兼容各种功能,系统能够专业化的匹配专业 ...

  6. 新萝卜家园win11全新专业版64位系统v2021.07

    新萝卜家园win11全新专业版64位系统v2021.07是一款专为游戏玩家准备的电脑操作系统,所需的运行文件也完全集成,实现软件安装运行更加稳定可靠.全新独创系统安装方式.同时应用商店也有了改进优化, ...

  7. 番茄花园win11专业版32位系统v2021.07

    番茄花园win11专业版32位系统v2021.07是一款非常好用的操作系统,这款系统在稳定性上进一步优化和提升,可以更好的获得整个纯版系统的稳定性,,能够很好的兼容各种功能,系统能够专业化的匹配专业的 ...

  8. 电脑公司win11 64位旗舰版镜像文件v2021.07

    电脑公司win11 64位旗舰版镜像文件v2021.07是目前非常受欢迎的电脑操作系统,系统中的功能十分的强大,能够智能判断出电脑的型号,然后为广大用户们安装相对应的驱动程序等,可以满足广大用户的所有 ...

  9. 技术员联盟win11旗舰版64位镜像v2021.07

    技术员联盟win11旗舰版64位镜像v2021.07是微软最新推出的电脑操作系统,这款系统带来全新的功能,如任务栏居中,右键刷新等等,采用最实用.最纯粹的系统,轻松满足用户多样化的系统服务需求,用户可 ...

  10. 深度技术win11旗舰稳定版v2021.07

    深度技术win11旗舰稳定版v2021.07是微软最新推出的电脑操作系统,这款系统带来全新的功能,如任务栏居中,右键刷新等等,采用最实用.最纯粹的系统,轻松满足用户多样化的系统服务需求,用户可以在本站 ...

最新文章

  1. 独家 | 如何跳出编程这个坑
  2. js 获取图片url的Blob值并预览
  3. python对象编程例子-python面向对象编程:python类和实例讲解
  4. MySQL 清理slowlog方法
  5. Leetcode 207. 课程表 解题思路及C++实现
  6. mybatis清除一级缓存的几种方法
  7. notepad++的好用快捷键整理
  8. 【AI-1000问】为什么LeNet5倒数第二个全连接层维度为84?
  9. 不吹不黑,赞一下应用运维管理的cassacdra
  10. SPI的4种工作模式(备忘)
  11. thinkphp-查询某一列的值column
  12. spring加载xml配置文件
  13. CPU漏洞可导致RSA被攻击
  14. js日期函数表达天,时,分,秒
  15. Mac python3连接mysql
  16. c语言void swap1,C语言的一些遗留问题(1):关于交换两个数的swap()函数的一些问题...
  17. 你应该知道的,十二大CNN算法
  18. BGP——基本概念3(路由聚合)
  19. 计算机一直显示配置更新失败怎么办,电脑更新新系统的时候出现配置更新失败问题怎么办...
  20. Python爬虫实例(2)-用BeautifulSoup爬取一个网页上的多张照片(以百度贴吧为例)

热门文章

  1. python节日快乐_【python】一键生成漂亮的节日快乐词云图
  2. 0703齐次方程-微分方程
  3. 大数据--数据仓库--维度退化
  4. 华为云服务器EulerOS镜像源设置方法
  5. java long初始化_java中long类型的变量想要初始化其值为空,要怎么实现?
  6. 前端实用的20个css技巧
  7. huawei路由器NAT配置
  8. Linux操作,su切换用户命令中有无横杠“-”的区别
  9. 蘑菇书 第一章绪论 习题
  10. Scratch模拟题(二级)_1