- Debugging Bare Metal Applications From L2 scratchpad
Debugging of bare metal applications that target the L2 scratchpad on PolarFire® SoC is possible, although, the scratchpad does need to be configured before starting a debug session. This guide will outline the recommended method of configuring the scratchpad before starting a debug session and outline the steps to debug the HSS and any bare metal application designed to target the scratchpad.
The easiest way to initialize the scratchpad is using a reduced HSS stored in eNVM which configures the scratchpad on boot and then goes into a while loop.
Once the reduced HSS has entered its while loop a debug session can be started and the
bare metal binary to be debugged can be loaded into the configured
scratchpad. If the application being debugged will train the DDR during its
start up then DDR training is not required in the reduced HSS. It is
possible to modify the HSS to not train DDR, and not progress to booting, using
the HSS Kconfig options CONFIG_SKIP_DDR
and CONFIG_SERVICE_BOOT
. If DDR is
required by the bare metal software and it expects DDR to be confgured for it
when it starts running then DDR training is required in the reduced HSS.
The following methodology is used to debug an application from the L2 scratchpad memory:
-
Build a version of the Hart Software Services to configure the L2 scratchpad but not boot
-
Program the modified HSS to eNVM and start up
-
Build the bare metal application under test in a "Loaded by bootloader configuration" so it performs no system configuration on startup
-
Download the application to be debugged to the L2 scratchpad using the debugger without resetting the target
-
Debug as normal
The HSS is built in two parts:
hss-l2scratch.elf
, which contains the run-time HSS code itselfhss-envm-wrapper.hex
, which includes a small decompressor, and thehss-l2scratch.elf
converted to a binary and compressed using DEFLATE.
It is possible to debug and step through the hss-l2scratch.elf
using the
methodology in this document.
The HSS code resides in eNVM, but its code size is too large so it needs to be compressed to do so. The HSS is built with the MSS configurator XML to divide the L2 area up as appropriate into L2 scratchpad, LIM, and L2-cache.
A small decompressor at the front of eNVM sets up L2 scratchpad as required,
copies across the HSS image, and executes this decompressed image. This is all
orchestrated from envm-wrapper/envm-wrapper_crt.S
.
There are two main reasons that we run from L2 scratchpad and not LIM:
-
Scratchpad supports Atomic instructions, which OpenSBI uses to sequence booting
-
Scratchpad is slightly faster than LIM
Make sure to clean, build and program the modified HSS to the eNVM
-
Rename an existing
.config
file from the top level HSS project directory (if present) so there is a backup of the existing configuration (if the standard HSS configuration is being built this step can be skipped). This can be done using the terminal view in SoftConsole using themove
command on Windows ormv
on Linux: -
Copy the
def_config
from the boards/target directory to the top level HSS project directory (note target should be replaced with the actual target, e.g mpfs-icicle-kit-es). Modify the following:Ensure that
CONFIG_SKIP_DDR=y
is present. Also ensure thatCONFIG_BOOT_SERVICE=y
is not present, and instead there is a line that explicitly mentions# CONFIG_SERVICE_BOOT
is not set, for example:# CONFIG_SKIP_DDR is not set CONFIG_SERVICE_BOOT=y
There should be no other mentions of either
CONFIG_SKIP_DDR
orCONFIG_SERVICE_BOOT
in the.config file
at this point. The modifications are shown below: -
If the GUI configuration was not used rename
def_config
to.config
by right clicking ondef_config
and selecting rename -
If an application is being debugged from the L2 scratchpad that is not the HSS, for example a payload intended to be booted by the HSS, updated XML will need to be generated using the MSS configurator to allocate more than the default 512k of the L2 to the scratchpad.
-
Import the updated XML to the boards/target/soc_fpga_design/xml directory. Ensure the updated XML name matches the XML used in the
.config
file. -
Right click on the hart-software-services project folder and select
Clean Project
-
Build the HSS using the
Default
build configuration -
Program the HSS to the eNVM using the SoftConsole
PolarFire SoC program non-secure boot mode 1
external tool configurationWhen configured like this, the HSS will start running from eNVM on a power-cycle or reset, setup L2 Scratch, jump to its runtime code but then idle.
At this point, as long as the SoC isn’t reset or power-cycled, it is possible to attach a debugger and download an ELF that targets L2 scratchpad, and to natively debug from it (set/remove breakpoints, step, run, etc.).
In the .config file
, ensure that CONFIG_SKIP_DDR=y
is present. Also ensure
that CONFIG_BOOT_SERVICE=y
is not present, and instead there is a line that
explicitly mentions # CONFIG_SERVICE_BOOT is not set
, for example:
CONFIG_SKIP_DDR=y
# CONFIG_SERVICE_BOOT is not set
There should be no other mentions of either CONFIG_SKIP_DDR
or
CONFIG_SERVICE_BOOT
in the .config
file at this point.
If an application is being debugged from the L2 scratchpad that is not the
HSS, for example a payload intended to be booted by the HSS, updated XML will
need to be generated using the MSS configurator to allocate more than the
default 512k of the L2 to the scratchpad. Import the updated XML to the
boards/target/soc_fpga_design/xml directory. Ensure the updated XML name
matches the XML used in the .config
file.
Make sure to clean, build and program the modified HSS to the eNVM:
$ make clean
$ make
$ make program
When configured like this, the HSS will start running from eNVM on a power-cycle or reset, setup L2 Scratch, jump to its runtime code but then idle.
At this point, as long as the SoC isn’t reset or power-cycled, it is possible to attach a debugger and download an ELF that targets L2 scratchpad, and to natively debug from it (set/remove breakpoints, step, run, etc.)
If the HSS is being debugged from L2 scratchpad these steps do not need to be followed. Please skip to the Debugging a bare metal application executing from L2 scratchpad section if debugging the HSS. These steps only need to be followed if a bare metal application is being reconfigured to run from the L2 scratchpad.
No default linker script is supplied to debug or run from the L2 scratchpad. To debug or run code from this location:
-
It is assumed that the reduced HSS will be used to pre-configure the system
-
A custom linker script will be created to ensure that the bare metal application does not conflict with the memory used by the HSS. I.e the HSS occupies the first 512K of L2 scratchpad, targeting a bare metal application will overwrite the HSS memory and would fail to boot if used as a payload.
It is recommended that the linker script to target L2 scratchpad is based off
the mpfs-ddr-loaded-by-boot-loader.ld
linker script provided with the MPFS
HAL. To modify this linker script to target the L2 scratchpad:
-
Create a copy of the
mpfs-ddr-loaded-by-boot-loader.ld
linker script namedmpfs-scratchpad-loaded-by-boot-loader.ld
-
Update the
scratchpad(rwx) : ORIGIN = 0x0A000000, LENGTH = 256k
field.a. Ensure the
ORIGIN
value is set to an appropriate start address that it0 doesn't conflict with the HSS. By default the HSS reserves 512K of L2 scratchpad soORIGIN = 0x0A040000
would be acceptable.b. The
LENGTH
field should also be updated to reflect the amount of L2 scratchpad memory available to the application. For example if a total L2 scratchpad size of 640K was configured, 128K would be available to the application soLENGTH = 128K
would be acceptable. -
In this linker script replace any entries locating code in
ddr_cached_32bit
withscratchpad
I.e all:
} > ddr_cached_32bit
entries should become:
} > scratchpad
-
In the:
Project properties -> C/C++ Build -> Settings
view select
Manage Configurations
and thenNew...
to create a new build configuration. -
Name the build configuration
Scratchpad-Debug
(or an appropriate name) and provide a description. Copy the build settings from the existingDDR-Release
build configuration. -
In the:
Project properties -> C/C++ Build -> Settings
->Tool Settings -> GNU RISC-V Cross C Linker -> General
view, ensure the
Scratchpad-Debug
build configuration is chosen and update the chosen linker script to point to thempfs-scratchpad-loaded-by-boot-loader.ld
linker script created in step 1.
This section is broken up into 3 sections:
-
Debugging a bare metal application executing from L2 scratchpad (for example from the PolarFire SoC Bare Metal Examples repository)
All bare metal applications from the PolarFire SoC Bare Metal Examples repository include 3 debug configurations:
-
[project name] hw all-harts debug
-
[project name] hw all-harts attach
-
[project name] renode all-harts debug
A new debug configuration will need to be created for L2 scratchpad debug.
In the "Debug Configurations" view:
-
Duplicate the
[project name] hw all-harts debug
configuration and name the new configuration[project name] hw all-harts debug-from-scratchpad
-
In the
Startup
tab disable theInitial Reset.
option (this will prevent the configured L2 scratchpad being reset) -
Apply the changes
Before starting a debug session ensure the reduced HSS has been programmed into
eNVM and has started running. It should have reached the Tiny CLI prompt and not
booted a payload. Once this has completed start the debug session by selecting
the [project name] hw all-harts debug-from-scratchpad
debug configuration and
clicking Debug
. The application can now be debugged as normal.
-
Restore the original HSS build configuration which was backed up in Using SoftConsole to configure a reduced HSS step 1 above by deleting the modified
.config
file and restoring from the original file -
Clean the HSS and rebuild
-
Launch the included hart-software-services debug configuration from the SoftConsole Debug Configurations (note this debug configuration is set up to not perform an initial reset on connection and simply download the application binary and start the debug session, this preserves the scratchpad configuration from the reduced HSS)
Important: at this point, revert your configuration changes from Using the
command line to configure a reduced HSS
and rebuild the HSS to ensure that the version you’ll be debugging will boot and
will train DDR. Ensure that CONFIG_SERVICE_BOOT=y
and # CONFIG_SKIP_DDR
is
not set are in the .config file:
# CONFIG_SKIP_DDR is not set
CONFIG_SERVICE_BOOT=y
There should be no other mentions of either CONFIG_SKIP_DDR
or
CONFIG_SERVICE_BOOT
in the .config
file at this point.
Make sure to clean and build the modified HSS:
$ make clean
$ make
In a terminal window, start OpenOCD manually:
${SC_INSTALL_DIR}/openocd/bin/openocd -c "set DEVICE MPFS" -f board/microsemi-riscv.cfg -c init
Next, in a separate terminal, run gdb and load an image as follows:
${SC_INSTALL_DIR}/riscv-unknown-elf-gcc/bin/riscv64-unknown-elf-gdb
Finally, at the (gdb) prompt, load the hss-l2scratch.elf image:
target remote localhost:3333
file Default/hss-l2scratch.elf
load Default/hss-l2scratch.elf
layout split
thread apply all set $pc=_start
At this point you can set any breakpoints etc. and start it running. For example:
break hss_main
continue