简介:面向OMAP-L138嵌入式开发者的FlashAndBootUtils工具包,专为解决基于TI OMAP-L138(集成Cortex-A8与C6000 DSP)系统的固件烧写与引导启动问题,适用于U-Boot移植、NAND/NOR/SPI启动配置及量产烧录等场景。压缩包共716个文件,以obj编译对象、module、c/h源码、makefile构建脚本、cmd链接配置和ais启动镜像为主,另有exe可执行工具与说明文档,整体体积仅3.65MB。内容覆盖从Bootloader到Flash编程工具、配置脚本、驱动与使用文档的完整链路,包含NAND、NOR、SPI_MEM等不同启动介质下的UBL版本,可直接参考或二次编译生成适合具体硬件环境的烧录镜像。开发者可按makefile和pjt工程文件梳理构建流程,利用ais和bin文件快速验证启动阶段,能大幅缩短OMAP-L138平台从裸机配置到系统启动的调试周期。目前已有104人学习,适合具备一定嵌入式基础、正在开展OMAP-L138或AM1808平台固件开发与维护的工程师。
1. 一块 OMAP-L138 板子起不来的那件事,多半出在 UBL 上
之前调一块 C6748 板子,上电后串口完全没有输出,JTAG 挂上去看,ROM bootloader 明明已经把片内 RAM 初始化好了,但跳转之后系统就死在原地。查到最后不是硬件问题,是 UBL(User Boot Loader)从 NAND 里读出来的第二级引导镜像布局不对。UBL 是 OMAP-L138 这类双核 SoC 上电后 ROM 加载的第一个用户程序,它负责初始化 DDR、PLL 和串口,再把应用从 SPI/NAND/NOR 里挪到内存。FlashAndBootUtils_2_29 就是 TI 针对 OMAP-L138、AM1808、C6748 这一系 C674x 芯片发布的全套引导工具包,里面有编好的 UBL .ais 镜像、烧录脚本和 C674x 启动汇编入口。适合正在做板级 bring-up、产线烧写或者想自己改 UBL 的嵌入式工程师。下面从解压开始,完整走一遍这套流程,把镜像选型、生成参数和烧写踩坑一次说清。
2. 先把 tar.gz 解开并从 .ais 文件名里读懂板子的引导介质
拿到OMAP-L138_FlashAndBootUtils_2_29.tar.gz,第一件事不是解压而是查包,个人习惯先用tar -tzf看完整文件列表,避免解出来发现某个 .ais 缺失再手忙脚乱。这个包里的东西不多,但每个文件名都直接对应一块具体的板子和启动介质,搞错型号或介质烧进去是起不来的。在 Linux 下解压 tar.gz 格式最常用这条命令,Windows 下用 7-Zip 打开压缩包然后解压到本地目录,效果一样:
tar -xzvf OMAP-L138_FlashAndBootUtils_2_29.tar.gz -C ./flash_boot_utils cd ./flash_boot_utils ls -l-x表示解压,-z处理 gzip 压缩,-v打印过程文件,-f指定压缩包名字,-C指定输出目录。解压完ls -l能看到完整的镜像清单,我实际拿到的一版包内容如下,不同渠道发布可能略有增删,以你解出来的实际文件为准:
UBL_C6748_SPI_MEM.ais UBL_OMAPL138_NAND.ais UBL_INTDEV0_NAND.ais UBL_AM1808_NAND.ais UBL_OMAPL138_NOR.ais UBL_INTDEV0_NOR.ais UBL_OMAPL138_SPI_MEM.ais UBL_INTDEV0_SPI_MEM.ais UBL_AM1808_SPI_MEM.ais start_c674x.asm这一排.ais文件是已经编译好的 UBL 镜像,.ais全称 Application Image Script,是 TI 的 ROM bootloader 专门识别的引导格式,不是烧进去的裸二进制。文件名里的三段信息决定了这块板子能不能正常启动,拆开看就是下面这个逻辑:
| 文件名字段 | 取值 | 含义 |
|---|---|---|
| 芯片型号 | OMAPL138 / AM1808 / C6748 | 同属 C674x 内核,但外设基地址和引脚复用不同,镜像不通用 |
| 启动介质 | SPI_MEM / NAND / NOR | SPI 串行 NOR Flash、并行 NAND Flash、并行 NOR Flash |
| INTDEV0 | 无 / INTDEV0 | 表示 TI 评估板内部默认存储布局,对应 L138 底板上的预设分区 |
INTDEV0这个标识很多人在这一步就选错了,它不是第三种芯片,而是开发板内部 NAND/NOR 存储分区方案的代号。如果你用的是 TI 的 LCDK 或 EVM,选带INTDEV0的版本,自定义底板根据实际 Flash 型号选择不带前缀的镜像。比如板子挂了镁光 MT29F2G08 NAND,通常选UBL_OMAPL138_NAND.ais,如果直接照抄官方板子设计,UBL_INTDEV0_NAND.ais更合适。
start_c674x.asm和这些.ais文件性质不同,它是汇编源码,给需要改 UBL 的人做入口初始化参考的,不是直接烧写文件。先用file命令确认是合法二进制再继续后续操作,避免解压过程中文件损坏导致烧进去黑屏。经验上,一个正常的 UBL .ais 文件一般 16K 到 64K 之间,如果你解出来某个 .ais 是 0 字节或者只有几百字节,多半是下载不完整,这个文件千万别烧。
3. 理清 AIS 镜像的生成机制:DDR 初始化、PLL 配置和串口参数都写在这
很多人以为 FlashAndBootUtils 里直接给的是 UBL 的 bin 文件,其实不是,.ais是经过打包的脚本化镜像,里面除了代码本体,还有一个挨一个的 AIS 命令段,比如设置 PLL、初始化 DDR、搬移代码、跳转执行。ROM bootloader 上电时把这些段按顺序解析执行,所以你在.ais里看到的一切都是 ROM 替你逐步完成的。这也是为什么有时候同一个 bin 文件,放在 NAND 上能启动、放在 NOR 上就不行——ROM 对 NOR 的初始化时序和 NAND 完全不同。
如果你手上只有一份源码工程,需要自己把编译好的ubl.bin打包成.ais,常见做法是用 TI 的 AISgen 工具,它接受一个 XML 配置文件,里面定义了 PLL 频率、DDR 时序和启动设备这几个关键参数,然后用命令行生成目标镜像。我在脚本里一般这样调用,重点看参数怎么对号入座:
aisgen -i ubl_config_l138_spi.xml -o UBL_OMAPL138_SPI_MEM.ais ubl.bin-i指定 XML 配置,-o指定输出文件名,最后跟编译好的裸 bin。实际工具版本可能叫dvg_aisgen,语法基本都是输入配置 + 输出镜像 + bin 文件这一套。下面这段配置覆盖了 456MHz 主频、133MHz DDR 和 SPI 启动的典型场景,也是我在这类板子上常用的初始化序列:
<ais_config> <pll_config> <!-- 外部晶振 24MHz,PLL 倍频到 456MHz --> <clock_freq_hz>456000000</clock_freq_hz> <ext_clock_hz>24000000</ext_clock_hz> </pll_config> <ddr_config> <!-- DDR2 时序参数,CL=3 --> <timing>normal</timing> <cas_latency>3</cas_latency> </ddr_config> <boot_device>spi</boot_device> <uart> <!-- 烧录调试串口波特率 --> <baudrate>115200</baudrate> </uart> </ais_config>里面对 UBL 能否正常加载影响最大的不是 PLL,是 DDR 时序。DDR 初始化失败的表现是 UBL 能跑、串口有输出,但一跳到应用就死,因为在 SDRAM 里取指失败。cas_latency这类参数必须和板上实际 DDR 颗粒一致,一般开发板手册都会给,没有就把timing设成safe,代价是启动变慢但稳定。
.ais镜像里还涉及一个所有做量产的人都会遇到的点:AIS 段有校验和。你用 AISgen 生成后不要拿十六进制编辑器随意改字节,只要改一处代码段,后面的校验段就全对不上了,ROM 会报错停在启动流程里。真要改,就改 XML 重新生成,或者回到编译环境改源码再编。另一个常见误用是跨介质复用镜像,UBL_OMAPL138_SPI_MEM.ais的 AIS 段里写死了 SPI 读取时序,直接改名烧到 NAND 里不可能启动,表面看是 UBL 结构问题,其实是 AIS 段类型不对。
4. 串口烧写 UBL 到 SPI/NAND/NOR 的完整操作与参数选择
镜像选对了,接下来就是用烧写工具把.ais写到 Flash 介质里。FlashAndBootUtils 这套工作流的标准烧录路径是:目标板先设置成 UART boot 模式(即从串口引导),上电后 OMAP-L138 的 ROM 会从 UART 接收 AIS 镜像并暂存在内部 RAM 执行,这个一次性引导程序再去初始化外部 Flash,把后续收到的镜像写入指定地址。TI 的 Serial Flash Host 工具对应这一流程,命令结构一般长下面这样:
sfh_OMAP-L138.exe -p COM3 -flash UBL_OMAPL138_SPI_MEM.ais-p COM3指定目标板所在串口号,-flash告诉工具进入烧写模式并写入后面这个 AIS 文件。执行前把板子拨码开关切到 UART boot,连好串口线,板子上电,工具连接成功后串口终端通常能看到 bootloader 返回的握手信号,这时再敲回车或者直接执行命令。配合 minicom 打开串口做监控,波特率要和 UBL XML 里 UART 配置保持一致,以下参数是这套工具最常见的默认组合:
stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenbcs8是 8 位数据位,-cstopb是 1 位停止位,-parenb关闭校验。不要在这里自作聪明改高波特率,UBL 引导阶段的串口驱动是按 115200 初始化的,除非你把 UBL 源码重新编译成 460800,否则改了只是烧写端单方面高速发送,ROM 端接收全是乱码。
4.1 NAND 烧写时容易忽略的坏块与 ECC 处理
NAND 和 NOR 的烧写参数差异比较大。NAND 有坏块问题,这是硬件特性不是烧写工具的 bug,所以 UBL 在 NAND 上的存放位置不能放在第 0 块。常见做法是把 UBL 放在块 1 或者由烧写工具自动跳过坏块,ROM 读到文件头后按物理块顺序搜索引导代码。烧写时如果报坏块跳过,属于正常现象,真正要关注的是 ECC 选项,NAND 烧写时命令里一般加留足够 ECC 空间的参数,H/W ECC 或 BCH8 是 OMAP-L138 上最常见的两种,默认 BCH8 适合 4KB 页的大页 NAND。烧完后立刻读回校验,不要依赖工具打印的 success,让工具 dump 一次 Flash 内容和原始 .ais 比对,这一步能筛掉大部分串口干扰导致的坏数据。
4.2 SPI NOR 烧写时关注写保护和时钟频率
SPI 介质走的是更简单的流程,没有坏块概念,但要注意 Flash 的 WP 写保护引脚。很多 SPI NOR 芯片出厂时状态寄存器里写保护是打开的,直接执行烧写会卡在擦除阶段。先把板子上 WP 引脚拉高或拉低(不同芯片极性不同,看数据手册),有些 Flash 还需要先用专用命令解除状态寄存器保护,再用 sfh 工具烧。烧写过程里如果反复报erase timeout,先怀疑供电电压,再怀疑写保护,最后才怀疑时钟太快,SPI 时钟不要直接拉满,串行 NOR 在高速下配合长走线容易毛刺,25MHz 左右是稳妥值。SPI 下 UBL 镜像的地址偏移和 NAND 也不同,工具默认从 Flash 基地址写入,不要手动加偏移,除非你同时改了 AIS 配置文件和 boot mode 的地址映射。
烧写完成后把板子断电,拨码切到对应介质启动模式,重新上电,这是整个流程的临门一脚。一个很容易让人误判的现象是:如果 Flash 里之前烧过旧版 UBL,新镜像写入后启动时串口打印的还是旧版本号,这个情况多数不是烧写失败,而是 Flash 擦除不完整或启动模式没切换对,板子实际是从另一片介质启动了。断电后再次确认拨码电平,比反复重新烧写更省时间。
5. 验证 .ais 镜像完整性并利用 start_c674x.asm 定制 UBL 入口
最后一步,也是产线上真正要用的技巧,是验证烧好的镜像和自定义 UBL 入口。.ais不是普通二进制,文件头有固定的 magic number,十六进制打开能看到0x41504954,ASCII 就是AIPT,这是 Application Image Script 的签名。写个一行命令快速确认某个 .ais 文件靠不靠谱,比烧进板子再睁眼等串口快得多,配合wc -c看一眼文件大小,就能排除九成下载损坏问题:
hexdump -C UBL_OMAPL138_NAND.ais | head -n 2正常输出的第一行应该以41 50 49 54开头,后面跟着段类型和长度。如果不是这个头,不管文件名写得多对都没意义,直接丢掉重下。
start_c674x.asm 是包里的汇编入口,负责 UBL 的初始跳转,通常在 C674x 的 boot 流程中占据最早的执行位置。原厂版本一般先设置 DSP 的栈指针,再把工作模式切到用户态准备调用 C 代码。在实际项目里我见过一种很实用的改法:板子上有多个 DDR 型号需要兼容,soft 配置对不上,就直接在这个汇编文件里给 DDR 初始化函数入口加一段冗余的参数填充,先尝试推荐时序,失败再降级到安全时序,然后把整个 UBL 重新汇编并用 AISgen 打包。这个方式比维护多个 .ais 省事得多,因为汇编入口是最先执行的地方,改这里不会破坏 UBL 后续的 C 代码框架。
还有一个值得花两分钟验证的点,start_c674x.asm里定义了 UBL 自身的加载地址,这个地址必须和.ais里第一个搬移段的目的地址一致。如果改了汇编入口地址但没改 AIS 段地址,表现是 UBL 在内存里跑飞,串口打几个乱码就静默。检查方式是反向汇编 .ais 里 Load 段的目标地址,再和汇编文件中的.set或_c_int00符号值比对,两边一致才说明入口配置闭合。
本文还有配套的精品资源,点击获取