[PATCH] arm64: zynqmp: Support semhosting boot method
Sean Anderson
sean.anderson at seco.com
Thu Feb 22 18:29:19 CET 2024
On 2/22/24 05:34, Michal Simek wrote:
>
>
> On 2/20/24 20:30, Sean Anderson wrote:
>> On 2/20/24 14:18, Michal Simek wrote:
>>>
>>>
>>> On 2/20/24 19:43, Sean Anderson wrote:
>>>> 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?
>>>
>>> That 0x1c bit are
>>> "Setting these bits disables the security gate for the PMU MDM and allows the PS TAP to connect to the PMU. All bits must be set to 1 for the security gate to be released. (POR reset only)"
>>>
>>> This is enabled to see PMU microblaze MDM. But I expect microblaze is not supported by OpenOCD but this makes it work for me.
>>
>> Yes, I know why you set these bits. But they should all be set already
>> (see e.g. my output above). So I am curious if they are not set for you.
>> If you have different values for the above registers, then there is
>> likely something different about your setup which could also cause your
>> below error.
>
> I tried on different zcu102 rev1.0 and I need to have it there.
Hm, maybe you can try https://review.openocd.org/c/openocd/+/5578
It has a different approach for this sort of thing.
>>
>>>>
>>>>> + sleep 5
>>>>
>>>> Part of my goal here is to remove "magic" sleeps like this so the boot
>>>> process goes faster.
>>>
>>> I get it. 5s is likely too much and didn't try to minimalize.
>>>
>>>>
>>>>> + 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.
>>>
>>> Can you provide more details about board you use?
>>> I can switch to different cable or different board but based on
>>> your config you are also using digilent smt2 NC module (without USB on it)
>>> that's why it is quite scary that I am not able to run it at higher freq.
>>
>> It's a custom design based on [1]. The carrier has a smt2 module on it
>> which is connected to the ZynqMP via the card edge connector.
>>
>> Regarding the clock speed, the datasheet for the smt2 [2] module says
>> the maximum speed is 30 MHz, but I use 25 MHz since DS925 says that is
>> the maximum speed for the ZynqMP (table 40). Maybe you are using a lower
>> VCCINT?
>>
>>> I will try different board or different cables.
>>> Do you know if standard xilinx cables are supported?
>>> This one
>>> https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fwww.xilinx.com%2fproducts%2fboards%2dand%2dkits%2fhw%2dusb%2dii%2dg.html&umid=720e2c50-55de-40c4-ac09-1623b19dfef2&auth=d807158c60b7d2502abde8a2fc01f40662980862-1c4afab79eea13f4f1554e802b0609bcea3cc2f7
>>> or black version?
>>
>> I have not tried those cables (nor do I have them on hand). I have used
>> the smt2 as well as the hs3 dongle. I also have a J-LINK, but I do not
>> have an adapter cable made.
>
> I have seen it working at 25MHz once but it is not stable with the same digilent module.
>
> Anyway please fix typo in subject and rebase it on the top of current master branch because it can't be applied and patch is ready to be merged.
https://lore.kernel.org/u-boot/20240222165230.2600974-1-sean.anderson@linux.dev/T/#u
--Sean
[Embedded World 2024, SECO SpA]<https://www.messe-ticket.de/Nuernberg/embeddedworld2024/Register/ew24517689>
More information about the U-Boot
mailing list