Closed fcuzzocrea closed 2 years ago
Hi @fcuzzocrea could you try setting your board to boot mode 0 (easiest way is the SoftConsole external tool) and try again? I'm wondering if Linux came up in the background from your eMMC when the HSS started up?
Yes, I can try that. For what I can say, before trying to flash the example, I manually stopped Linux from autoboot by hitting a key.
@hughbreslin but I have to recompile the whole HSS ? I just tried trough softconsole external tools to set Bootmode 0, and the procedure ended up correctly according to the logs, but now when I switch off and on the board the HSS splash screen does not come up anymore
The HSS is still present just that boot mode 0 is idle boot - you could re-program with the reference design job which should re-set the boot mode or re-build the HSS and either use the boot mode programmer in softconsole or use make program from the command line to program the eNVM and set the boot mode
Alright - then, selecting idle boot using SoftConsole had a worse effect, at least on my machine. I am not even able to load the program on the board. What I did after selecting the idle boot from soft console was:
fcuzzocrea@Latitude-5420:~$ /opt/openocd/bin/openocd --command "set DEVICE MPFS" --command "set COREID 1" --file /opt/openocd/share/openocd/scripts/board/microsemi-riscv.cfg
xPack OpenOCD (Microchip SoftConsole build), x86_64 Open On-Chip Debugger 0.10.0+dev-00859-g95a8cd9b5-dirty (2020-10-21-21:16)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
MPFS
1
Info : only one transport option; autoselect 'jtag'
do_board_reset_init
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : Embedded FlashPro6 (revision B) found (USB_ID=1514:200b path=/dev/hidraw1)
Info : Embedded FlashPro6 (revision B) CM3 firmware version: F4.0
Info : clock speed 6000 kHz
Info : JTAG tap: mpfs.cpu tap/device found: 0x0f81a1cf (mfg: 0x0e7 (GateField), part: 0xf81a, ver: 0x0)
Info : datacount=2 progbufsize=16
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 5 harts
Info : hart 0: currently disabled
Info : hart 1: XLEN=64, misa=0x800000000014112d
Info : hart 2: currently disabled
Info : hart 3: currently disabled
Info : hart 4: currently disabled
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
fcuzzocrea@Latitude-5420:~/.local/microchip/SoftConsole-v2021.1/extras/home/polarfire-soc-bare-metal-examples/applications/mpfs-pmp-demo/mpfs-pmp-app-u54-1/DDR-Release$ /home/fcuzzocrea/.local/microchip/SoftConsole-v2021.1/riscv-unknown-elf-gcc/bin/riscv64-unknown-elf-gdb mpfs-pmp-app-u54-1.elf
GNU gdb (xPack GNU RISC-V Embedded GCC (Microsemi SoftConsole build), 64-bit) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=riscv64-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://github.com/sifive/freedom-tools/issues>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help". Type "apropos word" to search for commands related to "word"... Really redefine built-in command "remote"? (y or n) [answered Y; input not from terminal] Reading symbols from mpfs-pmp-app-u54-1.elf... (gdb) set mem inaccessible-by-default off (gdb) set $target_riscv=1 (gdb) set arch riscv:rv64 The target architecture is assumed to be riscv:rv64 (gdb) target remote localhost:3333 0x000000002000312e in ?? () Loading section .text, size 0x2780 lma 0x80000000 Loading section .sdata, size 0x10 lma 0x80002780 Ignoring packet error, continuing... Loading section .data, size 0xe30 lma 0x80002790 Load failed
- Observe the following output from OpenOCD:
Info : accepting 'gdb' connection on tcp/3333 Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001002). Increase the timeout with riscv set_command_timeout_sec. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: Failed to read priv register. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Warn : negative acknowledgment, but no packet pending Warn : negative acknowledgment, but no packet pending Warn : negative acknowledgment, but no packet pending Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: Failed to read priv register. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Warn : negative acknowledgment, but no packet pending Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (7002). Workaround: increase "set remotetimeout" in GDB ^Cshutdown command invoked Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: Abstract command ended in error 'busy' (abstractcs=0x10001102) Error: Timed out after 2s waiting for busy to go low (abstractcs=0x10001102). Increase the timeout with riscv set_command_timeout_sec. Error: unable to resume hart 1 Error: dmstatus =0x00000382 Error executing event gdb-detach on target mpfs.hart1_u54_1:
Info : Embedded FlashPro6 (revision B): closing the device
I had to manually kill it
Apologies I misread your first message - did you program the demo into emmc / SD card after building it? There are additional steps in the readme to run this demo as a HSS payload.
Aaah, sorry, I was too fast in trying it.
So in essence this application runs in the same way of my custom application run. In my use case, instead of generating an HSS payload I generate a payload for my custom bootloader which then load the app (which has been programmed into an SPI flash), copies it into the LIM and jump to it using the jump_to_application() funtcion. And this chain works correctly.
What I want to do is to be able to load the raw application (so to speak, the ELF file produced after the build), directly into the LIM, using OpenOCD or an external JTAG programmer (for example, a Lauterbach debugger).
This thing works when the application is compiled with IMAGE_LOADED_BY_BOOTLOADER 1, as all the code which is needed to initialize the SoC is executed, but it does not in the following scenario:
In this scenario you end up into trap_from_machine_mode(), for reasons I fail to understand (as in the case of loading the application as payload and then jumping with jump_to_application() it loads correctly).
The usefulness of this is to be able to attacch GDB to the running application in order to debug the code (either using SoftConsole or directly GDB). Is it possible to achieve this goal using this example? So at least I have a starting working point in SoftConsole environment to understand the mechanism and then replicate it into my custom bootloader/application/build environment.
Hi @fcuzzocrea I'm a bit confused - have you modified the application to run from the LIM? The standard configuration is to run from the DDR.
Is there a typo here by any chance? The usefulness of this is to be able to attacch GDB to the running application in order to debug the code (either using SoftConsole or directly GDB). Is it possible to achieve this goal using this example?
- the SoftConsole example contains a debug configuration to attach to the running application, have you tried this when running the standard configuration the demo is set up for when it runs as a payload?
Also is the 0 here a typo? your application is compiled with IMAGE_LOADED_BY_BOOTLOADER 0, so it expects that a bootloader already initialized the SoC, and is linked against the LIM
- if set to 0 the application should not expect a bootloader to have initialized the SoC.
No, I did not touched the application. And yes that was a typo. And probably I tried the wrong example.
Actually, my goal was not to achieve an attach configuration, my goal was to be able to load into the LIM (or RAM, whatever) an application built with IMAGE_LOADED_BY_BOOTLOADER 1 trough an external JTAG debugger and start executing it (without the need of programming it first into any external medium).
This is useful when you are debugging an application which is supposed to be loaded by a bootloader, and it is linked against he LIM (or equivalently, the RAM) but you want to quickly try it, without programming it into an external medium before.
Actually, today, I was partially able to achieve my goal with this snippet of code (kanged and adapted from the jump_from_application() which I found into the examples), which is run by my bootloader after the SoC has been initialized:
void wait_for_debugger(HLS_DATA* hls, MODE_CHOICE mode_choice,
uint64_t next_addr)
{
/* Store current hardid */
uint32_t hartid = read_csr(mhartid);
/* Restore PLIC to known state */
__disable_irq();
PLIC_init();
/* Disable all interrupts: */
write_csr(mie, 0);
switch (mode_choice) {
default:
case M_MODE:
/**
* User application execution should now start and never return
* here....
*/
write_csr(mepc, next_addr);
break;
case S_MODE:
/**
* User application execution should now start and never return
* here....
*/
write_csr(mepc, next_addr);
break;
}
register unsigned long a0 asm("a0") = hartid;
register unsigned long a1 asm("a1") = (unsigned long)hls;
/* Hold for debugger to upload the app */
__asm__("ebreak");
__asm__ __volatile__("mret" : : "r"(a0), "r"(a1));
__builtin_unreachable();
}
of course, since my application is linked against the LIM, the entry point is 0x8000000, so I just hardcode this value into next_addr.
What happens here is that after i select M mode and store into the register the needfuls, a break point is triggered, so the code halts and waits.
At this point, with Trace32 I am able to execute an attach to the bootloader, manually load my application into the LIM, the program counter is set to 0x8000000, and when I press GO the application loads correctly.
This does not work when I use OpenOCD + GDB though. For some reasons, in this specific scenario the board ends up into a trap.
What I do is:
Power on the board, and the bootloader hits the ebreak
Fire up OpenOCD with :
/opt/openocd/bin/openocd --command "set DEVICE MPFS" --command "set COREID 0" --file /opt/openocd/share/openocd/scripts/board/microsemi-riscv.cfg
Fire up GDB and load the app:
Reading symbols from build/debug/c3app.elf...
(gdb) set mem inaccessible-by-default off
(gdb) set $target_riscv=1
(gdb) set arch riscv:rv64
The target architecture is set to "riscv:rv64".
(gdb) target extended-remote localhost:3333
Remote debugging using localhost:3333
0x0000000020221a9c in ?? ()
(gdb) load
Loading section .text, size 0x22220 lma 0x8000000
Loading section .sdata, size 0x70 lma 0x8022220
Loading section .data, size 0x3930 lma 0x8022290
Loading section .sdram, size 0x1388 lma 0x8025bc0
Start address 0x0000000008000000, load size 159560
Transfer rate: 9 KB/sec, 13296 bytes/write.
(gdb) tb _start
0x0000000008000004 in reset_vector ()
(gdb) si
Temporary breakpoint 1, 0x0000000008000008 in reset_vector ()
(gdb) si
0x000000000800000c in reset_vector ()
0x0000000008000014 in reset_vector ()
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
trap_from_machine_mode (regs=0x1001830, dummy=808472691, mepc=134217752) at ../../ext/pfsoc_platform/mpfs_hal/common/mss_mtrap.c:755
755 i++; /* added some code as SC debugger hangs if in loop doing nothing */
I would like to know what OpenOCD is doing different from Lauterbach Trace32 to make the app go to a trap.
Just a brief update to let you know that I was able to achieve my goal using ebreak. Probably it is just an hack, but maybe could be useful for someone else in future.
Basically I have created a wait_for_debugger() function:
void wait_for_debugger(HLS_DATA* hls, MODE_CHOICE mode_choice,
uint64_t next_addr)
{
/* Store current hardid */
uint32_t hartid = read_csr(mhartid);
/* Restore PLIC to known state */
__disable_irq();
PLIC_init();
/* Disable all interrupts: */
write_csr(mie, 0);
switch (mode_choice) {
default:
case M_MODE:
/**
* User application execution should now start and never return
* here....
*/
write_csr(mepc, next_addr);
break;
case S_MODE:
/**
* User application execution should now start and never return
* here....
*/
write_csr(mepc, next_addr);
break;
}
register unsigned long a0 asm("a0") = hartid;
register unsigned long a1 asm("a1") = (unsigned long)hls;
/* Hold for debugger to upload the app */
__asm__("ebreak");
__asm__ __volatile__("mret" : : "r"(a0), "r"(a1));
__builtin_unreachable();
}
Of course I know the value of next_addr
as the entry point of the elf I want to load is the start of the LIM, so I can just hardcode it.
When my bootloader is started from a debugging environment (Trace32 or OpenOCD+GDB), it executes the function and then hits the ebreak, so wait for the application to be loaded in the LIM.
With GDB I do:
fcuzzocrea@Latitude-5420:~$ riscv64-unknown-elf-gdb build/debug/c3app.elf
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Really redefine built-in command "remote"? (y or n) [answered Y; input not from terminal]
Reading symbols from build/debug/c3app.elf...
(gdb) set mem inaccessible-by-default off
(gdb) set $target_riscv=1
(gdb) set arch riscv:rv64
The target architecture is set to "riscv:rv64".
(gdb) target extended-remote localhost:3333
Remote debugging using localhost:3333
0x000000002022149a in ?? ()
(gdb) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
Starting program: /home/fcuzzocrea/Documenti/Progetti/core3_template_app/build/debug/c3app.elf
Disabling abstract command writes to CSRs.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000000020221ed8 in ?? ()
(gdb) load
Loading section .text, size 0x22200 lma 0x8000000
Loading section .sdata, size 0x70 lma 0x8022200
Loading section .data, size 0x3930 lma 0x8022270
Loading section .sdram, size 0x1388 lma 0x8025ba0
Start address 0x0000000008000000, load size 159528
Transfer rate: 9 KB/sec, 13294 bytes/write.
(gdb) continue
Continuing.
And my application loads correctly.
As I said, this probably it is just an hack, and can hardly be integrated into an IDE to allow interactive debugging, but at least it is working and I can use GDB from the CLI.
Since your bootloader is running and probably using the LIM start address for data/bss etc, halting it with ebrake before you load your application to the LIM start address makes sense to me.
Closing this issue since you have a it working with Trace32 as well as OpenOCD+GDB. Please feel free to reopen if we need to discuss this further.
This issue can be seen as a follow up of what I tried in here https://github.com/riscv/riscv-openocd/issues/662 in order to be able to program an arbitrary custom application into the LIM using OpenOCD, when running on my custom bootloader (both the bootloader and the application are built using the baremetal library, the bootloader is built using IMAGE_LOADED_BY_BOOTLOADER 0 and the application is built using IMAGE_LOADED_BY_BOOTLOADER 1) in my custom build environment (not SoftConsole based). Not being able to achieve my goal, I decided to analyze how this example was working, but I wasn't able to make it work.
To resume what I did:
I flashed reference design ver 2021.11 (which also ships HSS, so the board was loaded with HSS).
Open up the latest release of the example in SoftConsole and then build it using the build button.
After, I just manually invoked OpenOCD:
The arguments match what SoftConsole default configuration is setting
After doing that I manually invoked SoftConsole GDB and instead of having the application output on the UART I got trapped:
Actually I also tried single stepping but it is not clear the cause why I end up in trap_from_machine_mode (at least to me):
JFYI, I also tried to load the application using SoftConsole and the mpfs-pmp-app-u54-1 hw hart1 attach configuration, but nothing happens.