[PATCH] arm64: zynqmp: Support semhosting boot method

Sean Anderson sean.anderson at seco.com
Tue Feb 20 19:43:29 CET 2024


On 2/20/24 13:24, Michal Simek wrote:
>
>
> On 2/16/24 17:09, Sean Anderson wrote:
>> On 2/16/24 11:03, Sean Anderson wrote:
>>> On 2/16/24 10:06, Michal Simek wrote:
>>>>
>>>>
>>>> On 2/16/24 14:48, Michal Simek wrote:
>>>>>
>>>>>
>>>>> On 2/15/24 20:31, Sean Anderson wrote:
>>>>>> On 2/15/24 14:08, Michal Simek wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 2/15/24 18:19, Sean Anderson wrote:
>>>>>>>> Currently, when we boot from JTAG we try to boot U-Boot from RAM.
>>>>>>>> However, this is a bit tricky to time, since the debugger has to wait
>>>>>>>> for SPL to initialize RAM before it can load U-Boot. This can result in
>>>>>>>> long waits, since occasionally initializing RAM (and other things in
>>>>>>>> psu_init) takes a long time to complete and the debugger must wait for
>>>>>>>> this worst case.
>>>>>>>>
>>>>>>>> Support semihosting if it is enabled, as it lets U-Boot tell the
>>>>>>>> debugger when we are ready for the image. This means we don't have to
>>>>>>>> wait any more than necessary. We don't change the default config to
>>>>>>>> ensure we don't break compatibility with existing debuggers that don't
>>>>>>>> expect us to hit semihosting breakpoints.
>>>>>>>>
>>>>>>>> Signed-off-by: Sean Anderson <sean.anderson at seco.com>
>>>>>>>> ---
>>>>>>>>
>>>>>>>>     arch/arm/mach-zynqmp/spl.c | 10 ++++++++--
>>>>>>>>     1 file changed, 8 insertions(+), 2 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
>>>>>>>> index a0f35f36faa..5af735aa5ce 100644
>>>>>>>> --- a/arch/arm/mach-zynqmp/spl.c
>>>>>>>> +++ b/arch/arm/mach-zynqmp/spl.c
>>>>>>>> @@ -9,6 +9,7 @@
>>>>>>>>     #include <image.h>
>>>>>>>>     #include <init.h>
>>>>>>>>     #include <log.h>
>>>>>>>> +#include <semihosting.h>
>>>>>>>>     #include <spl.h>
>>>>>>>>     #include <linux/delay.h>
>>>>>>>>
>>>>>>>> @@ -66,6 +67,11 @@ void spl_board_init(void)
>>>>>>>>     }
>>>>>>>>     #endif
>>>>>>>>
>>>>>>>> +static u32 jtag_boot_device(void)
>>>>>>>> +{
>>>>>>>> +       return semihosting_enabled() ? BOOT_DEVICE_SMH : BOOT_DEVICE_RAM;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>     void board_boot_order(u32 *spl_boot_list)
>>>>>>>>     {
>>>>>>>>            spl_boot_list[0] = spl_boot_device();
>>>>>>>> @@ -75,7 +81,7 @@ void board_boot_order(u32 *spl_boot_list)
>>>>>>>>            if (spl_boot_list[0] == BOOT_DEVICE_MMC2)
>>>>>>>>                    spl_boot_list[1] = BOOT_DEVICE_MMC1;
>>>>>>>>
>>>>>>>> -       spl_boot_list[2] = BOOT_DEVICE_RAM;
>>>>>>>> +       spl_boot_list[2] = jtag_boot_device();
>>>>>>>>     }
>>>>>>>>
>>>>>>>>     u32 spl_boot_device(void)
>>>>>>>> @@ -97,7 +103,7 @@ u32 spl_boot_device(void)
>>>>>>>>
>>>>>>>>            switch (bootmode) {
>>>>>>>>            case JTAG_MODE:
>>>>>>>> -               return BOOT_DEVICE_RAM;
>>>>>>>> +               return jtag_boot_device();
>>>>>>>>     #ifdef CONFIG_SPL_MMC
>>>>>>>>            case SD_MODE1:
>>>>>>>>            case SD1_LSHFT_MODE: /* not working on silicon v1 */
>>>>>>>
>>>>>>> Good timing. Can you please tell me how to test this? What's the setup?
>>>>>>> Which debugger are you using?
>>>>>>
>>>>>> I am using OpenOCD with the patches at https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2freview.openocd.org%2fc%2fopenocd%2f%2b%2f8133&umid=6e1be473-0b3f-4bc4-a4f0-403592e74baf&auth=d807158c60b7d2502abde8a2fc01f40662980862-afc15b07b0f91c910f832185958363d84f990a08
>>>>>>
>>>>>
>>>>> I am trying it on the top of the latest git but getting issue with event block and no idea how to fix it.
>>>>>
>>>>> # sudo openocd -f /usr/local/share/openocd/scripts/interface/ftdi/digilent_jtag_hs3.cfg -f /usr/local/share/openocd/scripts/target/xilinx_zynqmp.cfg
>>>>> Open On-Chip Debugger 0.12.0+dev-01509-g6d288937cb2d (2024-02-16-12:22)
>>>>> Licensed under GNU GPL v2
>>>>> For bug reports, read
>>>>>       https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fopenocd.org%2fdoc%2fdoxygen%2fbugs.html&umid=6e1be473-0b3f-4bc4-a4f0-403592e74baf&auth=d807158c60b7d2502abde8a2fc01f40662980862-f501ab9aa5516ff666e387e53598fd624398f1bc
>>>>> Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
>>>>> wrong # args: should be "-event <event-name> <event-body>"
>>>>>
>>>>>
>>>>> Do you know how to fix it?
>>>>
>>>>
>>>> I actually bisect it and found that it is caused by
>>>> jtag: rewrite jim_jtag_configure() as COMMAND_HANDLER
>>>> ea2e26f7d521f5755b4bfda7bf12d99650277421
>>>
>>> Interesting. I have been testing with 0.12.
>>>
>>>> # sudo openocd -f /usr/local/share/openocd/scripts/interface/ftdi/digilent_jtag_smt2_nc.cfg -f /usr/local/share/openocd/scripts/target/xilinx_zynqmp.cfg
>>>
>>> FWIW after installing the udev rules I do not need sudo
>>>
>>>> Open On-Chip Debugger 0.12.0+dev-01512-g214206ebb972 (2024-02-16-15:38)
>>>> Licensed under GNU GPL v2
>>>> For bug reports, read
>>>>      https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fopenocd.org%2fdoc%2fdoxygen%2fbugs.html&umid=6e1be473-0b3f-4bc4-a4f0-403592e74baf&auth=d807158c60b7d2502abde8a2fc01f40662980862-f501ab9aa5516ff666e387e53598fd624398f1bc
>>>> none separate
>>>> Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
>>>> Info : Hardware thread awareness created
>>>> boot_apu
>>>> Info : Listening on port 6666 for tcl connections
>>>> Info : Listening on port 4444 for telnet connections
>>>> Warn : An adapter speed is not selected in the init scripts. OpenOCD will try to run the adapter at very low speed (100 kHz).
>>>> Warn : To remove this warnings and achieve reasonable communication speed with the target, set "adapter speed" or "jtag_rclk" in the init scripts.
>>>> Info : clock speed 100 kHz
>>>> Info : TAP uscale.tap does not have valid IDCODE (idcode=0x48e70126)
>>>> Info : JTAG tap: uscale.ps tap/device found: 0x24738093 (mfg: 0x049 (Xilinx), part: 0x4738, ver: 0x2)
>>>> Info : JTAG tap: uscale.tap tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5)
>>>> Info : JTAG tap: uscale.ps tap/device found: 0x24738093 (mfg: 0x049 (Xilinx), part: 0x4738, ver: 0x2)
>>>> Error: JTAG-DP STICKY ERROR
>>>> Error: [uscale.a53.0] Examination failed
>>>> Warn : target uscale.a53.0 examination failed
>>>> Info : [uscale.axi] Examination succeed
>>>> Info : starting gdb server for uscale.a53.0 on 3333
>>>> Info : Listening on port 3333 for gdb connections
>>>> Info : gdb port disabled
>>>>
>>>> but with zcu102 I am still not able to connect because error above.
>>>> The same behavior with recording SOM IDs I see on kv260 (via hs3 cable).
>>>> It looks like that not everything is working for zynqmp.
>>>
>>> Is this with the boot mode set to JTAG? If so, you will not be able to
>>> examine any of the CPUs until you have released them from reset. So you
>>> should be able to run
>>>
>>>          targets uscale.axi
>>>          boot_pmu /path/to/pmu-firmware.bin
>>>          boot_apu /path/to/u-boot-spl.bin
>>>
>>> to boot a CPU. If you want to silence the above error, you can add
>>>
>>>          uscale.a53.0 configure -defer-examine
>>>
>>> to your config. So the full command would be
>>>
>>> $ openocd -f interface/ftdi/digilent_jtag_smt2_nc.cfg \
>>>          -f target/xilinx_zynqmp.cfg \
>>>          -c 'uscale.a53.o configure -defer-examine' \
>>>          -c init -c 'targets uscale.axi' \
>>>          -c 'boot_pmu /path/to/pmu-firmware.bin' \
>>>          -c 'boot_apu /path/to/boot.bin'
>>>
>>> Let me know if that works for you.
>>
>> Oh, and I forgot to mention, but if you are testing semihosting then you will need to add
>>
>> -c 'uscale.a53.0 arm semihosting enable'
>>
>> to the end of that. I also find setting the semihosting base directory with
>>
>> -c 'uscale.a53.0 arm semihosting_basedir $IMAGEDIR'
>>
>> to be helpful.
>>
>> As you can imagine this is a long command line, so I have a config which looks like
>>
>> source [find interface/ftdi/digilent_jtag_smt2_nc.cfg]
>> adapter speed 25000
>> source [find target/xilinx_zynqmp.cfg]
>> uscale.a53.0 configure -defer-examine
>>
>> proc boot {imagedir machine} {
>>          targets uscale.axi
>>          boot_pmu "${imagedir}/pmu-firmware-${machine}.bin"
>>          boot_apu "${imagedir}/u-boot-spl.bin"
>>          uscale.a53.0 arm semihosting enable
>>          uscale.a53.0 arm semihosting_basedir $imagedir
>> }
>>
>> which I invoke like
>>
>> $ openocd -f my_config.cfg -c init -c 'boot /path/to/images my-machine'
>
>
> ok. 0.12.0 version is working better. I am able to load firmware to APU but I was not able to load pmufw. It was saying timeout like this.
>
>> boot_pmu /mnt/disk/som/pmu_obj.bin
> /usr/local/bin/../share/openocd/scripts/target/xilinx_zynqmp.cfg:173: Error: Timed out waiting for PMU firmware
> in procedure 'boot_pmu'
> in procedure 'resume_pmu' called at file "/usr/local/bin/../share/openocd/scripts/target/xilinx_zynqmp.cfg", line 232
> at file "/usr/local/bin/../share/openocd/scripts/target/xilinx_zynqmp.cfg", line 173
>>
>
> Then I looked at pmu and use below snipset which I use on xsdb to make it visible for debugger and also small waiting time.
>
>
> @@ -141,6 +146,13 @@ add_help_text halt_pmu "Halt the PMU in preparation for loading new firmware.\
>         This should be matched with a call to resume_pmu."
>  proc halt_pmu {} {
>         set axi $::_CHIPNAME.axi
> +
> +       puts "Enable PMU target"
> +       set val [$axi read_memory 0xFFCA0038 32 1]
> +       $axi write_memory 0xFFCA0038 32 [expr {$val | 0x1C0}]

These should already be set. See table 39-3 in UG1085. Although I seem
to have a combination of 39-2 and 39-3:

    > targets uscale.axi
    > # BOOT_MODE_USER BOOT_MODE_POR
    > mdw 0xff5e0200 2
    0xff5e0200: 00000000 00000000
    > # jtag_chain_cfg jtag_chain_status jtag_sec jtag_dap_cfg
    > mdw 0xffca0030 4
    0xffca0030: 00000000 00000003 0000003f 000000ff

Do you see these values in the JTAG boot mode?

> +       sleep 5

Part of my goal here is to remove "magic" sleeps like this so the boot
process goes faster.

> +       puts "PMU target should be enabled">         set val [$axi read_memory $::IPI_PMU_0_IER 32 1]
>         $axi write_memory $::IPI_PMU_0_IER 32 [expr {$val | $::IPI_PMU_0}]
>
> With that I am able to test your patch but it is kind of slow.
> Max freq I am able to use on zcu102 is 2MHz which is far from 15MHz used by xsdb.

I have been using the maximum 25 MHz speed without issue.

> After some time I am seeing
>
> Error: Invalid ACK (4) in DAP response
> Polling target uscale.a53.0 failed, trying to reexamine
> Error: Invalid ACK (0) in DAP response
> Error: Could not initialize the APB-AP
> Examination failed, GDB will be halted. Polling again in 100ms
> Error: Invalid ACK (0) in DAP response
> Polling target uscale.a53.0 failed, trying to reexamine
> Error: Invalid ACK (0) in DAP response
> Error: Could not initialize the APB-AP
> Examination failed, GDB will be halted. Polling again in 300ms
> Error: Invalid ACK (0) in DAP response
> Polling target uscale.a53.0 failed, trying to reexamine
> Error: Invalid ACK (0) in DAP response
> Error: Could not initialize the APB-AP
> Examination failed, GDB will be halted. Polling again in 700ms
> Error: Invalid ACK (0) in DAP response

So this indicates the APU is either inaccessable or still in reset. To
confirm, you get this after running boot_pmu and then boot_apu?

For reference I get

Open On-Chip Debugger 0.12.0 (2023-08-14-15:03)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
boot
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi tdo_sample_edge falling"
Info : clock speed 25000 kHz
Info : JTAG tap: uscale.tap tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5)
Info : JTAG tap: uscale.ps tap/device found: 0x04721093 (mfg: 0x049 (Xilinx), part: 0x4721, ver: 0x0)
Info : JTAG tap: uscale.tap tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5)
Info : JTAG tap: uscale.ps tap/device found: 0x04721093 (mfg: 0x049 (Xilinx), part: 0x4721, ver: 0x0)
Info : starting gdb server for uscale.a53.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : gdb port disabled
Info : Loading PMU firmware /path/to/pmu-firmware.bin to 0xffdc0000
Info : uscale.a53.0: hardware has 6 breakpoints, 4 watchpoints
Info : uscale.a53.0 cluster 0 core 0 multi core
uscale.a53.0 halted in AArch64 state due to debug-request, current mode: EL3H
cpsr: 0x200002cd pc: 0xfffc64fc
MMU: disabled, D-Cache: disabled, I-Cache: disabled
Info : Loading APU0 firmware /path/to/u-boot-spl.bin to 0xfffc0000
semihosting base dir: /path/to/u-boot/

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333

--Sean

[Embedded World 2024, SECO SpA]<https://www.messe-ticket.de/Nuernberg/embeddedworld2024/Register/ew24517689>


More information about the U-Boot mailing list