"Software Command-line Tool (XSCT) is an interactive and scriptable command-line interface to the Vitis IDE. As with other AMD tools, the scripting language for XSCT is based on the tools command language (Tcl). You can run XSCT commands interactively or script the commands for automation."
The project demonstrates how the tool can be used for configuration of Zynq UltraScale+ HOST USB compliance mode test procedure
JTAG Boot Mode
XSCT communicates with targets over JTAG interface and JTAG boot mode is recommended to enable the communication. While on evaluation boards there are switches to manipulate boot mode pins, the HW based approach is less available on custom boards. JTAG communication still happens with different boot mode, the difference is that it's master boot method in that case, it means that PS tries to load and execute external boot images, while JTAG boot mode assumes slave boot method where PS remains in idle mode while the boot image loads.
Note: The slave boot method is always a non-secure mode of booting.
Let's see how we can force PS into JTAG boot mode by means of XSCT script from KRIA documentation
proc boot_jtag { } {
############################
# Switch to JTAG boot mode #
############################
targets -set -filter {name =~ "PSU"}
# update multiboot to ZERO
mwr 0xffca0010 0x0
# change boot mode to JTAG
mwr 0xff5e0200 0x0100
# reset
rst -system
}
boot_jtag
the code defines and calls procedure boot_jtag which
- Connects to PSU target Processor Subsystem for UltraScale (PSU)
- Writes to Multi Boot CSU register next boot address 0x0
- Writes to BOOT_MODE_USER registerJTAG boot mode
- Resets the PS
PS initialization can be done with pmufw.elf and fsbl.elf (orzynqmp_fsbl.elf)taken from device correspondent vitis platform or petalinux project:
#### Bring the core out of reset => Load the FSBL with the USB3.0 setting
#Add the Microblaze PMU to target
targets -set -nocase -filter {name =~ "PSU"}
mwr 0xFFCA0038 0x1FF
# Download PMUFW to PMU
target -set -filter {name =~ "MicroBlaze PMU"}
puts "Downloading pmufw"
dow pmufw.elf
where jtag_sec (CSU) Register is used to disable CSU security and
targets -set -nocase -filter {name =~ "PSU"}
# write bootloop
mwr 0xffff0000 0x14000000
#E in below command brings only A53-0 out of reset.
mwr 0xFD1A0104 0x380E
# Download FSBL to A53 #0
targets -set -filter {name =~ "Cortex-A53 #0"}
puts "Downloading fsbl"
dow fsbl.elf
writing RST_FPD_APU (CRF_APB) Register
Registers Addressesthe article refers to the registers by names, while XSCT can address them by addresses which can be found in the Zynq UltraScale+ Devices Register Reference (UG1087), for instance the GCTL (GCTL-USB3_XHCI-Register) absolute address is 0x00FE20C110 for controller instance 0, and PORTSC absolute address is 0x00FE200430 for the controllerApparently there is 70701 - Zynq UltraScale+ - USB3.0 Host/Device compliance test procedure specifying all the registers addresses for the test
Bitmasks based operations syntax examples can be found in psu_init.tcl, the script performing PS initialization in JTAG mode. The file can be extracted from XSA if you unzip it, or found already extracted in Vitis platform project or petalinux one ( <proj dir>/project-spec/hw-description/psu_init.tcl)In the end of the file you can find procedures using arguments, variables and bit-wise operations like the following
proc psu_mask_write { addr mask value } {
set curval "0x[string range [mrd -force $addr] end-8 end]"
set curval [expr {$curval & ~($mask)}]
set maskedval [expr {$value & $mask}]
set maskedval [expr {$curval | $maskedval}]
mwr -force $addr $maskedval
}
DelaysSometimes we have to allow the target to complete the task pausing script execution for a while. It can be achieved with tcl command after with delay in milliseconds.
after 1000
Debugging messagesFormatted messages strings can be generated with tcl format command, for instance PORTSC variable value in hex format can be printed out with
puts [format "PORTSC = 0x%x" $PORTSC]
Final scriptConnecting everything together and adding the procedure implementation, we get a script like the following one:
proc boot_jtag { } {
############################
# Switch to JTAG boot mode #
############################
targets -set -filter {name =~ "PSU"}
# update multiboot to ZERO
mwr 0xffca0010 0x0
# change boot mode to JTAG
mwr 0xff5e0200 0x0100
# reset
rst -system
}
boot_jtag
#### Bring the core out of reset => Load the FSBL with the USB3.0 setting
#Add the Microblaze PMU to target
targets -set -nocase -filter {name =~ "PSU"}
mwr 0xFFCA0038 0x1FF
# Download PMUFW to PMU
target -set -filter {name =~ "MicroBlaze PMU"}
puts "Downloading pmufw"
dow pmufw.elf
con
targets -set -nocase -filter {name =~ "PSU"}
# write bootloop and release A53-0 reset
mwr 0xffff0000 0x14000000
mwr 0xFD1A0104 0x380E
# Download FSBL to A53 #0
targets -set -filter {name =~ "Cortex-A53 #0"}
puts "Downloading fsbl"
dow fsbl.elf
con
after 1000
proc set_usb3_compliance_mode {} {
#### Set GCTL.PORTCAPDIR = 1 => 0xFE20C110 = PRTCAPDIR[13:12]=0x1 - PRTCAPDIR: Port Capability Direction (PrtCapDir) - 2'b01: for Host configurations
set GCTL_PORTCAPDIR "0x[string range [mrd -force 0xFE20C110] end-8 end]"
puts [format "GCTL_PORTCAPDIR = 0x%x" $GCTL_PORTCAPDIR]
set GCTL_PORTCAPDIR [expr {(($GCTL_PORTCAPDIR & ~(0x3<<12)) | (0x01<<12))}]
mwr -force 0xFE20C110 $GCTL_PORTCAPDIR
set GCTL_PORTCAPDIR "0x[string range [mrd -force 0xFE20C110] end-8 end]"
puts [format "GCTL_PORTCAPDIR = 0x%x" $GCTL_PORTCAPDIR]
#### Put the host controller into compliance mode using the commands below
#### PORTSC &= 0xFFFEFE1F => 0xFE200430 = ((Xil_In32 0xFE200430) & 0xFFFEFE1F)
set PORTSC "0x[string range [mrd -force 0xFE200430] end-8 end]"
puts [format "PORTSC = 0x%x" $PORTSC]
set PORTSC [expr {$PORTSC & 0xFFFEFE1F}]
mwr -force 0xFE200430 $PORTSC
set PORTSC "0x[string range [mrd -force 0xFE200430] end-8 end]"
puts [format "PORTSC = 0x%x" $PORTSC]
#### PORTSC |= 0x10140 => 0xFE200430 = (Xil_In32 0xFE200430) | 0x10140)
set PORTSC [expr {$PORTSC | 0x10140}]
mwr -force 0xFE200430 $PORTSC
set PORTSC "0x[string range [mrd -force 0xFE200430] end-8 end]"
puts [format "PORTSC = 0x%x" $PORTSC]
#### Wait for some time
after 1000
#### Set GUSB3PIPECTL.HstPrtCmpl = 1
#### This will transmit CP0 pattern (0xFE20C2C0[30] = 1)
set GUSB3PIPECTL_HstPrtCmpl "0x[string range [mrd -force 0xFE20C2C0] end-8 end]"
set GUSB3PIPECTL_HstPrtCmpl [expr {(($GUSB3PIPECTL_HstPrtCmpl & ~(0x1<<30)) | (0x01<<30))}]
mwr -force 0xFE20C2C0 $GUSB3PIPECTL_HstPrtCmpl
set GUSB3PIPECTL_HstPrtCmpl "0x[string range [mrd -force 0xFE20C2C0] end-8 end]"
puts [format "GUSB3PIPECTL_HstPrtCmpl = 0x%x" $GUSB3PIPECTL_HstPrtCmpl]
after 1000
#### Enter into the next compliance pattern:
#### Set GUSB3PIPECTL.HstPrtCmpl = 0 => (0xFE20C2C0[30] = 0)
set GUSB3PIPECTL_HstPrtCmpl [expr {($GUSB3PIPECTL_HstPrtCmpl & ~(0x1<<30))}]
mwr -force 0xFE20C2C0 $GUSB3PIPECTL_HstPrtCmpl
set GUSB3PIPECTL_HstPrtCmpl "0x[string range [mrd -force 0xFE20C2C0] end-8 end]"
puts [format "GUSB3PIPECTL_HstPrtCmpl = 0x%x" $GUSB3PIPECTL_HstPrtCmpl]
after 1000
#### Set GUSB3PIPECTL.HstPrtCmpl = 1
set GUSB3PIPECTL_HstPrtCmpl [expr {(($GUSB3PIPECTL_HstPrtCmpl & ~(0x1<<30)) | (0x01<<30))}]
mwr -force 0xFE20C2C0 $GUSB3PIPECTL_HstPrtCmpl
set GUSB3PIPECTL_HstPrtCmpl "0x[string range [mrd -force 0xFE20C2C0] end-8 end]"
puts [format "GUSB3PIPECTL_HstPrtCmpl = 0x%x" $GUSB3PIPECTL_HstPrtCmpl]
#### This will transmit the next compliance pattern (0xFE20C2C0[30] = 1)
}
set_usb3_compliance_mode
with the following output:
GCTL_PORTCAPDIR = 0x693004
GCTL_PORTCAPDIR = 0x691004
PORTSC = 0x2a0
PORTSC = 0x2a0
PORTSC = 0x2a0
GUSB3PIPECTL_HstPrtCmpl = 0x410c8002
GUSB3PIPECTL_HstPrtCmpl = 0x10c8002
GUSB3PIPECTL_HstPrtCmpl = 0x410c8002
Comments
Please log in or sign up to comment.