尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

全志A33 U-Boot移植:GPIO配置与硬件手册协同避坑指南

全志A33 U-Boot移植:GPIO配置与硬件手册协同避坑指南 1. 为什么A33的U-Boot移植不是“照着手册抄代码”那么简单全志A33开发板的U-Boot移植是嵌入式Linux工程师绕不开的一道坎。但凡在论坛里搜过“全志A33 uboot 移植”你大概率会看到两类帖子一类是“已解决谢谢”另一类是“卡在串口没输出求大佬帮忙”。前者没说怎么解决的后者往往连硬件手册第几页都没翻对。我第一次接手A33项目时也以为就是把官方SDK里的sun8i_a33配置复制过来改改DDR参数、加个设备树节点烧进去就能跑。结果连续三天串口只有上电瞬间的乱码之后彻底静默——连U-Boot的启动logo都看不到。问题出在哪不是代码写错了而是我们误把“移植”当成了“搬运”。A33的U-Boot启动流程本质是一场与硬件物理特性的精密协同从晶振起振是否稳定到复位信号持续时间是否满足SoC要求从电源管理ICPMIC的上电时序是否被正确初始化到SD卡控制器引脚的驱动能力是否足够驱动特定型号的TF卡再到最关键的——GPIO复位后默认状态是否与外设电路设计冲突。这些细节不会出现在U-Boot源码的board/sunxi/目录下它们只藏在《A33 User Manual》第4章“Power Management and Reset”和第7章“Pin Multiplexing and GPIO Control”的交叉引用里。比如手册里明确写着“PB0-PB7在复位后默认为输入高阻态但若外部电路连接了10kΩ下拉电阻则实际电平为低此时若该引脚被配置为UART0_RXD功能将导致UART接收端被强制拉低无法接收任何数据。”——这正是我那三天串口静默的根因开发板原理图上UART0_RXDPB7确实接了下拉电阻而U-Boot默认配置里没有在early_init_f()阶段主动将PB7设置为上拉输入模式。所以这份避坑指南不讲“如何编译U-Boot”也不列“十个必须修改的文件”它只聚焦一件事如何让U-Boot的软件逻辑真正读懂并尊重A33这块芯片的物理语言。核心关键词就四个全志A33、U-Boot、GPIO配置、硬件手册。后面所有内容都是围绕这四者之间的咬合关系展开。如果你正拿着一块A33开发板手边摊着一份PDF版《A33 User Manual》还有一份刚从git clone下来的U-Boot源码那么接下来的内容就是帮你把这三样东西真正“焊”在一起的操作手册。2. 硬件手册不是字典而是启动时序的密码本很多人把《A33 User Manual》当成一本技术词典需要查某个寄存器地址时才翻开。这种用法在U-Boot移植阶段是致命的。手册真正的价值不在于告诉你“GPIO寄存器地址是0x01C20800”而在于揭示“为什么这个地址必须在复位后第127个时钟周期内被首次写入”。这就要求我们必须把手册当作一本启动时序的密码本逐页解码其背后隐藏的物理约束。2.1 启动流程的三个不可跳过的物理阶段A33的启动过程被严格划分为三个由硬件自动控制的阶段U-Boot的代码只能在第三阶段介入。理解这三阶段是避免90%移植失败的前提BootROM阶段硬件固化SoC上电后内部BootROM固件首先运行。它只做三件事检测启动介质SD卡、SPI Flash、eMMC、加载位于介质首扇区的boot0镜像、校验boot0的CRC并跳转执行。这个阶段完全不可编程所有配置如SD卡时钟频率、eMMC总线宽度都由BootROM内部硬编码决定。手册第3章“Boot Process”明确指出“BootROM仅支持最大25MHz的SD卡时钟且不支持SDHC卡的CMD6命令”。这意味着如果你的开发板使用的是Class10高速SD卡而BootROM又恰好选择了SD卡启动那么即使U-Boot里把SD控制器配置成50MHz系统也永远卡在BootROM的初始化环节——因为硬件根本不认识这个速度。boot0 boot1阶段固件引导boot0是一个极小的汇编程序它的唯一任务是加载并执行boot1。boot1则复杂得多它负责初始化DRAM控制器这是整个移植中最关键、最易出错的一步并加载U-Boot的u-boot.bin到内存中。手册第5章“DRAM Initialization”给出了一个关键参数tRFCRow Refresh Cycle Time对于A33标配的512MB DDR3颗粒该值必须设置为160ns。但boot1源码里通常只提供一个默认值如120ns。如果开发板使用的DDR颗粒批次不同tRFC实际需求为180ns而boot1仍按120ns刷新DRAM就会在U-Boot启动几秒后开始出现随机位翻转表现为内核panic或文件系统损坏。这个参数必须根据你手上那块开发板实际焊接的DDR颗粒型号丝印在芯片上去查阅该颗粒的Datasheet再反向修正boot1中的配置。U-Boot阶段软件接管只有当boot1成功将U-Boot加载到内存并跳转后我们熟悉的C语言世界才开始。但此时硬件并非一张白纸。GPIO、UART、I2C等外设的初始状态全部由前两个阶段的硬件行为和boot1的初始化代码共同决定。例如手册第7章“GPIO Configuration”表格里列出的“Reset State”指的是SoC复位引脚释放后的瞬间状态而非U-Bootboard_init_f()函数执行时的状态。很多初学者直接在board_init_f()里配置GPIO却忽略了boot1可能已经将某个GPIO配置为其他功能如USB PHY供电使能导致U-Boot的配置被覆盖。提示不要试图跳过boot0/boot1去“直刷U-Boot”。A33的启动链是硬性依赖U-Boot二进制文件必须由boot1加载。你所能修改的只是boot1本身需重新编译烧录和U-Boot的配置。2.2 GPIO章节的隐藏陷阱复位状态与功能复用的双重博弈《A33 User Manual》第7章“Pin Multiplexing and GPIO Control”是移植过程中查阅频率最高的章节但也是最容易被误解的章节。问题在于它同时描述了两种截然不同的状态复位后的默认状态Reset State和功能复用选择Function Selection而这两者之间存在微妙的时序差。手册中一个典型表格如下简化示意Pin NameReset StateFunction 0Function 1Function 2Function 3PB0Input Hi-ZUART0_TXDPWM0SPI0_CSGPIOPB1Input Hi-ZUART0_RXDPWM1SPI0_CLKGPIO..................初看之下似乎只要把PB0/PB1选为Function 0就能得到UART0。但手册第7.2节“GPIO Configuration Sequence”里埋着一句关键描述“When a pin is configured as a GPIO (Function 3), its direction and output value are controlled by the GPIO registers. However, if the pin is configured for an alternate function (Function 0-2), the GPIO registers have no effect on its electrical behavior.” 这句话的意思是一旦你把PB1配置为UART0_RXDFunction 0那么后续对PB1的GPIO寄存器如PDATA,PDR的任何写操作都将被硬件忽略。它的电平完全由外部电路和UART控制器内部逻辑决定。这个细节直接导致了一个经典坑UART接收无响应。原因往往是开发板原理图上PB1UART0_RXD为了抗干扰串联了一个100Ω电阻并在PCB上连接了一个10kΩ下拉电阻到GND。在复位后PB1处于Input Hi-Z状态下拉电阻将其拉至低电平。当U-Boot的UART驱动初始化时它会向UART控制器发送一个“清空接收FIFO”的命令但此时RXD线上持续的低电平会被UART控制器误判为一个“持续的起始位”从而进入一种等待停止位的死锁状态再也无法接收后续数据。解决方案不是在U-Boot里去“读取PB1的电平”而是必须在boot1阶段或者在U-Boot的极早期_start汇编代码中将PB1配置为“上拉输入”模式Pull-up Input覆盖掉外部下拉电阻的影响。这个配置需要操作的是PUL寄存器Pull-up/Pull-down Control Register其地址在手册中有明确说明但绝不会出现在U-Boot的drivers/serial/serial_sunxi.c文件里。2.3 电源管理章节被忽视的“静默杀手”A33的电源管理单元PMU是另一个深坑集中地。手册第4章“Power Management Unit”里关于AXP221A33常用PMIC的描述常常被快速略过。但恰恰是这里藏着让系统“看似正常启动实则暗中崩溃”的元凶。一个真实案例某款A33开发板在U-Boot阶段一切正常能打印logo能进入命令行甚至能ping通网络。但一旦尝试加载内核系统就在解压内核镜像时卡死。反复检查DDR配置、内核镜像完整性、设备树兼容性均无异常。最终发现问题出在PMIC的DCDC3通常为VDD-CPU供电的电压设定上。手册第4.5.2节明确指出“DCDC3的默认输出电压为1.2V但A33的CPU核心电压推荐工作范围为1.0V~1.3V具体值需根据实际运行频率动态调整。若DCDC3电压设置过高如1.25V在CPU进行高频运算时会导致PMIC过热保护触发瞬间切断供电造成系统硬复位。” 而U-Boot默认的axp221驱动恰恰没有在board_init_f()中动态调整DCDC3电压它只是简单地读取了PMIC的默认值并保持不变。因此正确的做法是在U-Boot的板级初始化代码中通常是board/sunxi/common/board.c添加一段针对axp221的定制化初始化。这段代码需要通过I2C总线读取axp221的REG_DCDC3寄存器根据当前目标CPU频率例如800MHz查表确定对应的最优电压如1.15V将计算出的电压值需转换为axp221的DAC编码写回REG_DCDC3。这个过程需要你手边不仅有《A33 User Manual》还得有AXP221 Datasheet以及一份详细的电压-频率对照表。它不是U-Boot标准流程的一部分却是让A33稳定运行的物理基石。3. GPIO配置实战从寄存器映射到引脚复用的完整闭环在A33上配置一个GPIO远不止是调用gpio_request()和gpio_direction_output()这么简单。它是一个涉及物理引脚、功能复用、电气特性、时序约束的完整闭环。下面以一个最典型的实战场景为例将PA12配置为LED控制引脚并确保其在U-Boot启动初期即可点亮。3.1 第一步定位物理引脚与功能复用组首先打开《A33 User Manual》第7章的“Pin Description”表格。找到PA12这一行。表格会显示Pin Name: PA12Reset State: Input Hi-ZFunction 0: NAND_D12Function 1: I2S0_MCLKFunction 2: PWM2Function 3: GPIO我们的目标是将其作为普通GPIO使用因此必须选择Function 3。但请注意手册在此处还有一个重要注释“PA12 is shared with NAND flash data bus. If NAND controller is enabled, PA12 cannot be used as GPIO.” 这意味着如果你的开发板设计中启用了NAND Flash作为启动介质那么PA12的Function 3GPIO就是被硬件锁定的强行配置会导致NAND控制器工作异常。因此第一步必须确认你的开发板原理图PA12是否真的连接到了LED还是它被用作了NAND_D12如果是后者你必须另选一个未被占用的GPIO比如PE15其Reset State为Output Low更适合驱动LED。3.2 第二步计算寄存器地址与位偏移A33的GPIO控制器采用分组管理每组如PA、PB、PC...有独立的寄存器块。手册第7.3节“GPIO Register Map”给出了基地址0x01C20800。每个组的寄存器偏移量是固定的PCTLPin Control Register用于选择功能复用偏移量为0x00PDATAPin Data Register用于读写数据偏移量为0x0cPDRPin Direction Register用于设置输入/输出偏移量为0x04对于PA组其基地址就是0x01C20800。那么PA_PCTL地址 0x01C20800 0x00 0x01C20800PA_PDR地址 0x01C20800 0x04 0x01C20804PA_PDATA地址 0x01C20800 0x0c 0x01C2080c接下来确定PA12在PCTL寄存器中的位域。手册规定每个引脚的功能选择由4位控制PA0对应PCTL[3:0]PA1对应PCTL[7:4]以此类推。因此PA12对应PCTL[47:44]因为12*448所以是第47到第44位。要将PA12设置为Function 3GPIO需要向PCTL[47:44]写入0b0011即十进制3。这是一个典型的位操作不能直接write32(0x01C20800, 0x00000003)因为这会覆盖掉PA0-PA11的配置。正确的做法是读取当前PA_PCTL的值清除PCTL[47:44]这4位用掩码0xFFFF0FFF将0b0011左移44位与步骤2的结果进行或运算将最终结果写回PA_PCTL。3.3 第三步配置方向与初始电平在PCTL设置好后才能安全地操作PDR和PDATA。PDR寄存器中每一位控制对应引脚的方向1为输出0为输入。PA12对应PDR[12]。因此要将其设为输出需向PDR[12]写1。PDATA寄存器中每一位代表对应引脚的输出电平1为高电平0为低电平。由于我们要点亮LED而常见电路是LED阳极接VCC阴极通过限流电阻接GPIO即低电平点亮所以我们需要将PA12输出为0。然而这里有一个关键的时序陷阱。手册第7.4节“GPIO Timing Requirements”指出“The direction register (PDR) must be written before the data register (PDATA) for the same pin. Writing PDATA before PDR may result in undefined output state.” 意思是必须先设置方向再设置电平。否则如果PDR[12]还是0输入而你先写了PDATA[12]0那么这个0会被当作一个输入电平采样而不是输出LED自然不会亮。因此完整的汇编级操作序列在U-Boot的board_init_f()之前或在arch/arm/cpu/armv7/sunxi/board.c的sunxi_board_init()中应为// 假设r0 0x01C20800 (PA base) ldr r1, 0x00000001 // bit mask for PA12 mov r2, #0x00000001 // set output direction str r2, [r0, #4] // write to PDR (offset 0x04) // now set output level to 0 (low) mov r2, #0x00000000 str r2, [r0, #0xc] // write to PDATA (offset 0x0c)3.4 第四步处理电气特性与上拉/下拉最后一步也是最容易被忽略的一步处理引脚的上下拉电阻。PA12的Reset State是Input Hi-Z这意味着它内部没有上拉或下拉。但在实际电路中如果LED的阴极直接接到PA12而阳极通过电阻接到VCC那么当PA12输出高电平时LED两端电压差接近0LED熄灭当输出低电平时LED导通。这看起来没问题。但问题在于U-Boot的启动过程很长。从SoC上电到boot1完成DRAM初始化再到U-Boot的C代码开始执行中间可能有数百毫秒的时间。在这段时间里PA12一直保持着Hi-Z状态。如果外部电路没有设计上拉或下拉电阻那么PA12的电平就是浮空的可能会被PCB上的杂散电容耦合出一个不确定的电平导致LED在启动过程中随机闪烁甚至在U-Boot还没来得及配置它时就短暂点亮给调试带来极大困扰。因此最佳实践是在原理图设计阶段就为所有用作输出的GPIO添加一个10kΩ的下拉电阻对低电平有效LED或上拉电阻对高电平有效LED。而在U-Boot代码中则需要在配置完PDR和PDATA后立即配置PUL寄存器Pull-up/Pull-down Control Register以确保软件配置与硬件设计一致。PUL寄存器的偏移量是0x08PA12对应PUL[12]。要启用下拉需向PUL[12]写0手册规定0Down,1Up。注意PUL寄存器的配置必须在PDR之后、PDATA之前进行。因为PUL的生效会影响引脚在Hi-Z状态下的默认电平而PDATA的写入会覆盖这个默认电平。顺序错误可能导致LED在配置过程中出现一次意外的闪烁。4. U-Boot移植全流程避坑清单从编译到烧录的12个生死关基于多年在A33平台上的实战经验我将整个U-Boot移植流程拆解为12个关键节点并为每个节点标注了“致命风险等级”★越多越危险和“典型症状”。这份清单不是教科书式的步骤罗列而是从血泪教训中提炼出的生存指南。4.1 环境准备工具链与SDK版本的隐性战争致命风险等级★★★★★典型症状编译通过但生成的u-boot.bin大小异常比正常值小20KB以上烧录后SoC无任何反应。根因解析A33的U-Boot高度依赖于arm-linux-gnueabihf-工具链的特定版本。官方SDK如sunxi-tools通常要求gcc 4.9.x。如果你使用了更新的gcc 7.5.0编译器会对某些内联汇编如__attribute__((naked))的启动代码进行过度优化导致_start入口点被破坏。更隐蔽的是新版binutils的ld链接器默认启用了--as-needed选项会丢弃一些U-Boot启动必需但未被显式调用的符号如__initcall_start造成board_init_f()函数根本不会被执行。避坑方案严格使用SDK文档指定的工具链版本。若必须升级务必在Makefile中添加LDFLAGS -Wl,--no-as-needed并在config.mk中禁用-O2优化改为-O1。同时用readelf -a u-boot.bin | grep Entry验证入口点地址是否为0x4a000000A33的默认加载地址。4.2 配置选择sun8i_a33与sun8i_a33_smp的抉择致命风险等级★★★★☆典型症状U-Boot能打印logo但无法识别SD卡mmc info命令返回No SD Card。根因解析sun8i_a33_smp配置是为多核SMP模式设计的它默认启用了CONFIG_SUNXI_SMP。而A33虽然是双核但其SMP支持在U-Boot中并不成熟且CONFIG_SUNXI_SMP会改变boot1的加载方式和内存布局导致SD卡控制器的DMA缓冲区地址错乱。避坑方案除非你明确需要在U-Boot中运行多核测试否则一律使用sun8i_a33_defconfig。在make menuconfig中手动确认System Type-ARM system type-Allwinner sun8i SoCs-sun8i A33被选中且SMP support未被勾选。4.3 设备树编译.dts与.dtsi的继承陷阱致命风险等级★★★☆☆典型症状U-Boot启动后printenv显示bootcmd为空fdt addr命令报错。根因解析A33的设备树文件结构是sun8i-a33.dts板级继承自sun8i-a33.dtsiSoC级。sun8i-a33.dtsi中定义了chosen节点其中包含stdout-path属性指向serial01c28000。但如果你的开发板使用的是UART1地址0x01c28400而你在sun8i-a33.dts中没有正确覆盖chosen/stdout-pathU-Boot的console初始化就会失败导致后续所有命令行交互失效。避坑方案在板级.dts文件中必须显式重写chosen节点chosen { stdout-path serial01c28400:115200n8; };并确保uart1节点的status okay;已被启用。4.4 DDR初始化boot1与U-Boot的参数接力致命风险等级★★★★★典型症状U-Boot启动后md.b 0x4a000000 10命令返回的内存内容全是0x00或0xff表明DRAM未被正确初始化。根因解析A33的DRAM初始化由boot1完成U-Boot只负责“接管”和“验证”。boot1的配置参数如DRAM_PARA存储在boot1镜像的固定偏移处。U-Boot在启动时会从这个偏移处读取参数并据此配置自己的内存管理。如果boot1的编译参数如DRAM_TYPE、DRAM_SIZE与你的开发板实际硬件不符U-Boot读取到的就是一组错误的参数它会用这组错误参数去“验证”一个本就错误的内存状态结果自然是失败。避坑方案boot1的配置必须与硬件100%匹配。你需要查阅开发板原理图确认DDR颗粒型号如MT41K256M16HA-125查阅该颗粒的Datasheet获取tRC,tRFC,tRP,tRAS等关键时序参数修改boot1源码中的include/configs/sun8i_a33.h填入这些精确参数重新编译boot1并用sunxi-fel工具将其烧录到SD卡的0x8000扇区。4.5 GPIO驱动drivers/gpio/gpio-sunxi.c的魔改必要性致命风险等级★★★☆☆典型症状gpio status命令能列出所有GPIO但gpio set 12命令执行后用万用表测量PA12电压无变化。根因解析标准U-Boot的gpio-sunxi.c驱动只实现了gpio_request(),gpio_direction_output()等基本API但它没有实现gpio_set_value()的底层寄存器操作。它依赖于一个名为sunxi_gpio_set_value()的函数而这个函数在旧版U-Boot中是空的return 0;。因此所有gpio set命令都只是在软件层面标记了状态根本没有写入硬件寄存器。避坑方案必须在drivers/gpio/gpio-sunxi.c中补全sunxi_gpio_set_value()函数。其核心逻辑就是前面3.3节描述的计算PDATA寄存器地址读-改-写。同时确保CONFIG_GPIO_SUNXI被正确启用并在板级配置中添加#define CONFIG_SUNXI_GPIO。4.6 烧录方式fel模式与sdcard模式的适用边界致命风险等级★★★☆☆典型症状用sunxi-fel烧录u-boot.fex后拔掉USB线系统无法启动。根因解析sunxi-fel是一种USB协议它允许主机通过USB直接向SoC的SRAM下载并执行代码。它非常适合调试阶段因为它绕过了BootROM和boot0/boot1。但u-boot.fex只是一个临时镜像它不会被永久写入SD卡。一旦断电SRAM内容丢失下次上电SoC还是会走正常的BootROM-boot0-boot1-U-Boot流程。如果你没有把u-boot.bin正确烧录到SD卡的0x8000扇区boot0之后那么断电后系统必然无法启动。避坑方案fel模式仅用于快速验证U-Boot是否能跑起来。最终量产必须使用dd命令将u-boot.bin写入SD卡dd ifu-boot.bin of/dev/sdX bs1024 seek8其中seek8表示跳过前8个扇区8*5124096字节因为boot0占用了前8个扇区。u-boot.bin的大小必须小于0x800032KB否则会覆盖boot1。4.7 网络启动CONFIG_CMD_NET与PHY驱动的强耦合致命风险等级★★★☆☆典型症状dhcp命令超时ping 192.168.1.1返回Timeout。根因解析A33的EMAC以太网MAC控制器需要与外部PHY芯片如LAN8720协同工作。U-Boot的CONFIG_CMD_NET选项只是启用了网络命令但drivers/net/sunxi_emac.c驱动必须正确初始化PHY。而PHY的初始化依赖于CONFIG_PHYLIB和具体的PHY驱动如drivers/net/phy/lan87xx.c。如果CONFIG_PHYLIB未启用或者PHY驱动未被编译进U-Boot那么EMAC控制器就无法与PHY建立通信链路。避坑方案在make menuconfig中必须启用Device Drivers-Network device support-Allwinner EMAC supportDevice Drivers-PHY Device support-PHY libraryDevice Drivers-PHY Device support-Lan87xx PHY support同时在板级.dts文件中确保emac节点的phy-handle属性正确指向了phy0且phy0节点的compatible属性为ethernet-phy-ieee802.3。4.8 调试串口CONFIG_DEBUG_UART的双刃剑致命风险等级★★☆☆☆典型症状开启CONFIG_DEBUG_UART后U-Boot启动速度变慢且printf输出延迟严重。根因解析CONFIG_DEBUG_UART启用的是U-Boot的底层调试串口它绕过了完整的UART驱动栈直接操作寄存器。这虽然能在驱动初始化前就输出信息但它会抢占CPU资源且其波特率是硬编码的通常是115200无法与你的终端软件协商。更重要的是它与正常的CONFIG_SYS_NS16550_SERIAL驱动共存时会产生资源冲突。避坑方案CONFIG_DEBUG_UART仅在“连串口输出都没有”的极端情况下使用如排查boot1问题。一旦U-Boot能正常打印logo就必须关闭它并专注于调试drivers/serial/serial_sunxi.c。日常开发应始终使用标准的CONFIG_SYS_NS16550_SERIAL。4.9 文件系统CONFIG_CMD_FAT与CONFIG_FS_FAT的依赖链致命风险等级★★☆☆☆典型症状fatls mmc 0:1命令返回Unknown command。根因解析fatls命令的实现依赖于CONFIG_CMD_FAT启用命令和CONFIG_FS_FAT启用FAT文件系统支持两个宏。但CONFIG_FS_FAT又依赖于CONFIG_GENERIC_FIND_FIRST_BIT等底层位操作函数。如果这些底层函数未被启用CONFIG_FS_FAT就会编译失败导致fatls命令不可用。避坑方案在make menuconfig中除了启用CONFIG_CMD_FAT还必须启用Library routines-Generic bit find functionsFile systems-FAT supportFile systems-Support for FAT filesystem4.10 环境变量CONFIG_ENV_IS_IN_MMC与分区的精确对齐致命风险等级★★★☆☆典型症状saveenv命令执行后重启系统环境变量恢复为默认值。根因解析CONFIG_ENV_IS_IN_MMC表示环境变量存储在eMMC/SD卡上。U-Boot默认将其存储在mmc 0:1第一个分区的起始扇区。但如果SD卡的第一个分区/dev/mmcblk0p1是从扇区2048开始的这是fdisk的默认对齐那么U-Boot写入的环境变量就会被写入到分区之外的空白区域下次读取时自然找不到。避坑方案必须在板级配置头文件如include/configs/sun8i_a33.h中明确定义环境变量的存储位置#define CONFIG_SYS_MMC_ENV_DEV 0 #define CONFIG_ENV_OFFSET 0x300000 /* 存储在SD卡的0x300000字节处即扇区0x600 */ #define CONFIG_ENV_SIZE 0x2000 /* 环境变量大小为8KB */然后用dd命令将一个8KB的空白文件/dev/zero写入到SD卡的0x600扇区作为环境变量的预留空间。4.11 内核加载bootz与bootm
返回列表