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
To execute the SPL in DDR interactive mode, and to tune the DDR settings, the SPL needs to be loaded into embedded RAM:
- manually (to be repeated after each reset):
- automatically by ROM code after each reset:
with STM32CubeProgrammer
You can use the CLI command to directly load the SPL into the embedded RAM for peripheral boot on USB or UART.
In this case the load with STM32Programmer needs to be repeated after each reset.
The manual connection is difficult in parallel of STM32Programmer: it is recommended to activate the compilation flag DDR_INTERACTIVE to force the interactive mode. |
The next example uses the Linux cli, but you can also use ST32CubeProgrammer for Windows (.bat file) with the same parameters.
USB
- Compile SPL with DDR_INTERACTIVE=1
- Select USB_Boot on the board
. - Connect USB to USB HS, reset the board and execute the STM32CubeProgrammer CLI command :
PC $> STM32_Programmer.sh -c port=usb1 -w spl/u-boot-spl.stm32 0x01 --start 0x01
UART
- Compile SPL with DDR_INTERACTIVE=1
- Select UART_Boot on the board
. - Connect board UART to the PC, reset the board and the STM32CubeProgrammer CLI command (with the correct tty interface : ttyS0 / ttyUSB0):
PC $> STM32_Programmer.sh -c port=/dev/ttyS0 br=115200 -w spl/u-boot-spl.stm32 0x01 --start 0x01
with GDB
- Compile SPL with DDR_INTERACTIVE=1
- Select "Engineering boot" = "Forced USB boot for flashing" on the board
. - After GDB connection, reset and attach to the target, execute the commands:
(gdb) file u-boot-spl.elf (gdb) load (gdb) set $dtb = __bss_end (gdb) restore spl/u-boot-spl.dtb binary $dtb
Warning: SPL DTB is not included in the ELF file by default; you need to load it manually with GDB at the correct location.
Boot from SD card
You can directly update SPL on the SD card used, and let the Boot ROM code load the binary for the next boot form SD card.
In this case, activate the DDR mode by pressing the 'd' key continously (DDR_INTERACTIVE=1 is not mandatory).
Writing the SPL to SDMMC on Linux PC
See 如何在SD卡上更新U-Boot to update partition 1 and 2 with partition <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 uses the DDR for U-Boot execution, so this method cannot be used during debug of the DDR settings and execution of the unitary (DDR) test..
To boot from SDCARD, the generated files must be written in 2 partitions :
- 1: spl/u-boot-spl.stm32
- 4: u-boot.img
The Linux command is:
PC $> STM32_Programmer.sh -c port=usb1 -w FlashLayout.tsv
With FlashLayout.tsv following STM32CubeProgrammer_flashlayout format, for example:
#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
You can also use programmer for Windows (.bat file) with the same parameters.