项目背景:

采用新唐的NUC977DK61Y芯片开发项目,项目中使用了LVGL8.3,FreeRTOS, 由于是开发播放器的控制器,界面会显示汉字,加入了utf-8的字库,导致bin文件很大(几十MB)

遇到问题:

  1. 当bin文件没有加入字体相关的代码时候,程序运行一点事情都没有,不会出现无法启动情况。
  2. 直接通过RAM运行在0x0 也没问题,能直接从内存运行。
  3. 当采用u-boot加载运行,问题就来了,无法启动,直接卡死在 串口输出:
1
2
2097152 bytes read: OK
## Starting application at 0x00000000 ...

串口输出截图

envgo.txt 文件内容

1
2
bootcmd=nand read 0 0x200000 0x200000;go 0;
bootdelay=0

解决方案:

排查内存分配是否有问题

排查过程,当时以为是内存爆了,各种修改LVGL和FreeRTOS内存配置,都是没有解决,意识到,已经不是内存溢出问题导致,问题应该出在其他地方。

排查看门狗

后来怀疑是不是u-boot加载大内核,触发了看门狗,后来在u-boot上加上复位看门狗的代码,然并卵,还是有这个问题,这个时候冷静的想想,已经不是看门狗问题。

最后排查u-boot

用经过几天的思考,百思不得其解,后来突发奇想,为什么不直接绕过u-boot,直接内存加载运行呢? 于是,打开NuWriter马上验证 NuWriter内存运行NUC977程序

结果就是一点问题都没有,程序正常运行 NuWriter内存运行NUC977程序

程序上唯一可能就是就是引导程序加载问题了。

同时注意到串口:

1
Read OK 2097152 bytes

于是找chat-gpt问了下: chat-gpt

然后我再次让chat帮我分析了下:

chat-gpt分析问题

帮我解析下这个u-boot的指令:bootcmd=nand read 0 0x200000 0x200000;go 0;

bootdelay=0

ChatGPT 这个u-boot的配置中有一个名为bootcmd的环境变量,它定义了在系统启动时要执行的一系列指令。这些指令在启动时被u-boot自动执行。具体来说,bootcmd包含两个主要指令,通过分号分隔:

nand read 0 0x200000 0x200000:这个指令从NAND Flash中读取数据。它的格式为:

1
2
3
4
5
nand read <load_addr> <nand_addr> <size>
<load_addr>:数据将被加载到内存的地址。在这里,是地址0。
<nand_addr>:NAND Flash中数据的起始地址。在这里,是0x200000。
<size>:要读取的数据大小。在这里,是0x200000。
这条指令的作用是从NAND Flash中读取0x200000字节的数据

我如果程序大小超过2MB该设置多少?

ChatGPT 如果你的程序大小超过2MB,你可能需要考虑适当增加bootdelay的值,以便在启动时给用户一些时间来进行干预或选择启动选项。bootdelay的值是等待用户输入的秒数。你可以根据实际需求设置一个合适的值,例如设置为5或10,以便在启动时有足够的时间进行干预。

例如,将bootdelay设置为5,表示u-boot将等待5秒钟,然后执行bootcmd。这给了用户足够的时间在启动时按下相应的键,如果需要的话,可以进入u-boot的命令行界面或者选择其他启动选项。

在u-boot的环境变量中,将bootdelay设置为5的示例如下:

1
bootdelay=5

请根据你的实际需求调整这个值。

User

帮我分析下这个文件的内促你占用大小:

1
2
3
4
5
Invoking: GNU ARM Cross Print Size
arm-none-eabi-size --format=berkeley "FreeRTOS.elf"
   text	   data	    bss	    dec	    hex	filename
3756968	   6333	37075232	40838533	26f2585	FreeRTOS.elf
Finished building: FreeRTOS.siz

ChatGPT

这是通过GNU ARM工具链中的arm-none-eabi-size工具对一个名为FreeRTOS.elf的可执行文件进行大小分析的输出。以下是各个部分的解释:

text: 可执行文件中的代码段(程序的指令部分)大小。在这里,大小为3756968字节。

data: 可执行文件中的数据段(全局变量等数据)大小。在这里,大小为6333字节。

bss: 未初始化的数据段(未初始化的全局变量等)大小。在这里,大小为37075232字节。

dec: 可执行文件的总大小(包括text、data和bss)。在这里,大小为40838533字节。

hex: 总大小的十六进制表示。

filename: 可执行文件的名称,这里是FreeRTOS.elf。

综合来看,这个可执行文件的总大小为40838533字节,或者约为39 MB。这包括了代码段、数据段以及未初始化的数据段。这是在嵌入式系统中的一个比较大的可执行文件大小,可能适用于相对较强大的嵌入式系统或者具备足够存储空间的环境。

你帮我修改下u-boot的命令,加载大小能加载50MB

抱歉对之前的回答有所误解。如果你希望修改u-boot中的nand read命令以支持更大的加载大小,你可以将加载大小修改为50MB。在你的bootcmd中,修改nand read命令的第三个参数即可。以下是修改后的示例:

1
bootcmd=nand read 0 0x200000 0x3200000; go 0;

在这里,0x3200000是50MB的十六进制表示。你可以根据需要调整这个值。确保你的目标设备的u-boot版本支持这样的修改,并且硬件能够支持更大的加载大小。

彻底解决

从chat的回答以及我查看envgo.txt来看,基本上已经可以确定问题了,是加载的字节数少了,导致没有加载完整程序进内存,于是修改对应的envgo.txt文件:

修改envgo.txt

1
2
bootcmd=nand read 0 0x200000 0x200000;go 0;
bootdelay=0

改为

1
2
bootcmd=nand read 0 0x200000 0x3200000; go 0;
bootdelay=0

将原来只加载2MB左右的数据,增加到加载到50MB 运行结果(串口输出):

1
2
3
Hit any key to stop autoboot:  0 

NAND read: device 0 offset 0x200000, size 0x3200000

问题完美解决