U-Boot SPL: DDR interactive mode
在U-Boot中, U-Boot SPL可以提供用于DDR配置的调试控制台。
它是STM32CubeMX DDR tuning tools使用的嵌入式部件。
DDR interactive mode
此模式在编译标志 CONFIG_STM32MP1_DDR_INTERACTIVE下定义。
当这个配置标志被激活时,有两种方式进入交互模式:
- 在控制台中加载SPL并按下字符 ‘d’ (适用于DDR)。
轮询只在启动序列的200毫秒内完成。
因此手动操作很困难,您应该在SPL启动期间一直按“d”键,直到DDR> 提示符出现。 - 通过在make选项中添加 DDR_INTERACTIVE=1 编译为强制DDR_INTERACTIVE模式
然后,SPL自动进入DDR模式:
PC $> DEVICE_TREE=<device tree name> DDR_INTERACTIVE=1 make
当DDR工具控制台可用时,在SPL信息标语之后显示以下输出:
0:DDR_RESET DDR>
交互模式使用与SPL控制台相同的UART,默认情况下,STMicroelectronics板使用UART4,且Bps = 115200 Bit = 8 Parity = None Stop = 1
DDR steps
DDR交互模式使用5个步骤来初始化DDR控制器和PHY(包括初始化期间发送给DDR的“模式寄存器” 0-3),并使用在设备树中找到的参数:
step | name | Description | DDR CTL state |
DDR PHY state |
DDR CTL registers |
DDR PHY registers |
---|---|---|---|---|---|---|
0 | DDR_RESET | Initial state Clock initialized 'param' initialized with Device Tree |
Reset | Reset | Reset Values | Reset Values |
1 | DDR_CTRL_INIT_DONE | Controller init done | Clocked | Reset | Init done with 'param.ctl' CTL register can be updated (command edit) |
Reset Values |
2 | DDR PHY_INIT_DONE | DDR PHY init done | Runnig Waiting PHY |
Clocked | - | Init done with 'param.phy' PHY register can be updated (command edit) |
3 | DDR_READY | DDR ready and ports are open test can be executed |
Running | Running | - | - |
4 | RUN | Continue execution (U-Boot load) | Running | Running | - | - |
commands available
使用:
- <type> = ctl, phy (适用于所有DDR控制器或PHY寄存器)
or one category: static, timing, map, perf, cal, dyn - <reg> = name of the register (dx0dqstr for example)
您可以执行以下命令:
- help: 显示帮助
- info: 管理DDR信息 (step, name, size and speed)
- info: 显示DDR信息
- info <param> <val>: 将 <param> 更改为 <value> (<param> = "step", "name", "size" or "speed")
- freq: 管理DDR PHY频率
- freq: 显示DDR频率
- freq <frequency>: 更改频率(以kHz为单位),仅允许在步骤0中使用
DDR>freq DDRPHY = 40000 kHz DDR> freq 523000 DDRPHY = 522999 kHz
- param: 管理输入参数(从设备树中读取
- param [type|reg]: 打印输入参数
- param <reg> <val>: 在步骤0中编辑参数
- print [type|reg]: 转储寄存器
- edit:修改DDR控制器和DDR PHY中的寄存器
在输入参数初始化之后,需要在正确的步骤中完成(设备树中的值)
- step 1 => CTRL 允许更新寄存器
- step 2 => PHY 允许更新寄存器
- step 3 => DDR 就绪(仅用于控制器和PHY的动态寄存器)
- edit [type|reg]: 修改DDR控制器或PHY中的值寄存器
- step: 管理步骤
- step: 列出可用步骤
- step [n]: 转到步骤 <n>
您可以使用“步骤0”重置并重新启动初始化序列
0:DDR_RESET 1:DDR_CTRL_INIT_DONE 2:DDR PHY_INIT_DONE 3:DDR_READY 4:RUN
- next: 转到下一步
- go: 继续执行U-Boot SPL(加载u-boot,与“步骤4”相同)
- reset: 重新启动机器
- test: 测试管理 : 请参阅 [q[#DDR test|next chapter]]
- tuning: 执行调整命令,现在只有一个子命令
- tuning <n>: 执行调整程序 <n>
- tuning help: 显示帮助消息,列出可用的优化过程
0:Read DQS gating:software read DQS Gating 1:Bit de-skew: 2:Eye Training:or DQS training 3:Display registers: 4:Bist config:[nbErr] [seed]
"param" 命令是测试修改后的设置的一种简单方法,因为它修改了输入参数 ( 'param' 从设备树中读取). 建议在 step 0处执行此命令。修改后的值将以正确的 #DDR steps应用。
“打印”和“编辑”命令直接访问CTRL和PHY寄存器,因此当驱动程序执行初始化步骤时,输入参数可以覆盖这些值。这些命令用于DDR初始化的详细调试。
Examples
DDR>info step = 3 : DDR_READY name = DDR3-1066/888 bin G 2x4Gb 533MHz v1.40 size = 0x40000000 speed = 533000 kHz
DDR>param cal ==phy.cal== dx0dllcr= 0x40000000 dx0dqtr= 0xffffffff dx0dqstr= 0x3db02000 dx1dllcr= 0x40000000 dx1dqtr= 0xffffffff dx1dqstr= 0x3db02000 dx2dllcr= 0x40000000 dx2dqtr= 0xffffffff dx2dqstr= 0x3db02000 dx3dllcr= 0x40000000 dx3dqtr= 0xffffffff dx3dqstr= 0x3db02000
DDR>print dx0dqstr dx0dqstr= 0x3db03001
DDR>print mstr mstr= 0x00040401
DDR test
要执行DDR测试,您需要进入“DDR就绪”步骤(步骤3)。
要生成测试列表,请在不使用任何参数的情况下执行“ test”命令:
DDR>step 3
DDR>test test:25 0:All: 1:Simple DataBus:[addr] 2:DataBusWalking0:[loop] [addr] 3:DataBusWalking1:[loop] [addr] 4:AddressBus:[size] [addr] 5:MemDevice:[size] [addr] 6:SimultaneousSwitchingOutput:[size] [addr] 7:Noise:[pattern] [addr] 8:NoiseBurst:[size] [pattern] [addr] 9:Random:[size] [loop] [addr] 10:FrequencySelectivePattern :[size] 11:BlockSequential:[size] 12:Checkerboard:[size] 13:BitSpread:[size] 14:BitFlip:[size] 15:WalkingOnes:[size] 16:WalkingZeroes:[size] 17:infinite read:[addr] 18:infinite write:[addr]
每个测试可以单独执行,并由其编号标识:
DDR>test 1 execute 1:Simple DataBus Result: Pass [address 0xc0000000]
可以使用测试0执行所有测试:
DDR>test 0 execute 0:All execute 1:Simple DataBus result 1:Simple DataBus = Passed execute 2:DataBusWalking0 running 100 loops at 0xc0000000 result 2:DataBusWalking0 = Passed execute 3:DataBusWalking1 running 100 loops at 0xc0000000 result 3:DataBusWalking1 = Passed .... check buffer. pattern = 00000001. check buffer. result 15:WalkingOnes = Passed Result: Pass [0/16 test failed]
Source code organization
- driver = |}} drivers/ram/stm32mp1/
- 设备树文件,用于 DDR 设置: arch/arm/dts/ | |}} arch/arm/dts/stm32mp15-*dtsi , 例如:
- arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | |}} stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
- arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binF.dtsi | |}} stm32mp15-ddr3-2x4Gb-1066-binF.dtsi
- arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | |}} stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
- arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binF.dtsi | |}} stm32mp15-ddr3-1x4Gb-1066-binF.dtsi
这些文件提供了定义列表:
#define DDR_<NAME> <VALUE>
并包含|}} stm32mp15-ddr.dtsi 为DDR控制器和PHY提供每个寄存器值。
这些DDR文件包含在使用所需DDR配置节点构建设备树所需的板文件 stm32mp157c_<board>-uboot.dts 中。
Load the SPL into embedded RAM
要在DDR交互模式下执行SPL并调整DDR设置,需要将SPL加载到嵌入式RAM中:
- 手动 (每次复位后都要重复):
- 每次复位后由ROM代码自动执行:
with STM32CubeProgrammer
您可以使用CLI命令将SPL直接加载到嵌入式RAM中,以通过USB或UART进行外围设备引导。
在这种情况下,每次复位后都需要重复STM32Programmer的加载。
与STM32Programmer并行执行时,手动连接很困难:建议将编译标志DDR_INTERACTIVE激活为 force the interactive mode. |
下一个示例使用Linux cli,但是您也可以使用具有相同参数的Windows ST32CubeProgrammer (.bat 文件)。
USB
- 使用DDR_INTERACTIVE=1编译SPL。
- 在板上选择 USB_Boot。
- 将USB连接到USB HS,重置板并执行 STM32CubeProgrammer CLI命令: :
PC $> STM32_Programmer.sh -c port=usb1 -w spl/u-boot-spl.stm32 0x01 --start 0x01
UART
- 使用 DDR_INTERACTIVE=1编译SPL。
- 在板上选择UART_Boot 。
- 将板子UART连接到PC,重置板子和 STM32CubeProgrammer CLI命令(使用正确的tty接口 : ttyS0 / ttyUSB0):
PC $> STM32_Programmer.sh -c port=/dev/ttyS0 br=115200 -w spl/u-boot-spl.stm32 0x01 --start 0x01
with GDB
- 使用 DDR_INTERACTIVE=1编译SPL
- 在板上选择"Engineering boot" = "Forced USB boot for flashing" 。
- GDB 连接后,重置并附加到目标,执行以下命令:
(gdb) file u-boot-spl.elf (gdb) load (gdb) set $dtb = __bss_end (gdb) restore spl/u-boot-spl.dtb binary $dtb
Warning: 默认情况下,ELF文件中不包括SPL DTB。 您需要使用GDB在正确的位置手动加载它。
Boot from SD card
您可以直接在使用的SD卡上更新SPL,并让Boot ROM代码为下一张引导形式的SD卡加载二进制文件。
在这种情况下,请连续按“ d”键激活DDR模式(不是强制性的DDR_INTERACTIVE=1 ).
Writing the SPL to SDMMC on Linux PC
请参阅 如何在SD卡上更新U-Boot 用以分区更新分区1和分区2<n> = /dev/mmcblk0p<n> or /dev/sdb<n> :
PC $> dd if=u-boot-spl.stm32 of=<dev>1 conv=fdatasync PC $> dd if=u-boot-spl.stm32 of=<dev>2 conv=fdatasync
Writing SPL in SDMMC with STM32CubeProgrammer
Warning: STM32CubeProgrammer使用DDR进行U-Boot执行,因此无法在DDR设置的调试和单一(DDR)测试的执行期间使用此方法。
要从 SDCARD 引导,必须将生成的文件写入2个分区
- 1: spl/u-boot-spl.stm32
- 4: u-boot.img
Linux命令是:
PC $> STM32_Programmer.sh -c port=usb1 -w FlashLayout.tsv
使用 FlashLayout.tsv 遵循 STM32CubeProgrammer_flashlayout 格式,例如:
#Option Id Name Type Device Offset Binary P 0x01 fsbl1 Binary SDMMC1 0x00004400 spl/u-boot-spl.stm32 PE 0x02 fsbl2 Binary SDMMC1 0x00044400 none P 0x03 ssbl Binary SDMMC1 0x00084400 u-boot.img.bin
您也可以使用具有相同参数的Windows程序(.bat文件)。