Bare Metal Tutorial

Is there a detailed bare metal tutorial anywhere?

The links and YouTube videos seems to be a little vague in details.

Thank you!

Maybe I should give more details…

I was able to make a project in SoftConsole

and I was able to make a config.yaml file

I’m having problems with the HSS Payload Generator and I’m trying to understand how things work in regards to loading specific functions to their respective harts/cores, e.g.- u54_1(), u54_2(), etc.

Hey @MisterHemi

Unfortunately the YouTube videos and Webinar series are what we have in terms of demos/tutorials.

To try and give you a bit of information (let me know if you need more) there are a few things that happen / need to be done:

  1. IMAGE_LOADED_BY_BOOTLOADER needs to be defined in the mss_sw_config.h file - this will tell the payload application its being loaded by a bootloader and doesn’t need to do any hardware configuration (e.g DDR training, setting up clocks and setting up the MSS I/O).
  2. MPFS_HAL_FIRST_HART and MPFS_HAL_LAST_HART need to be set correctly for your application depending on the harts being used.
  3. Once you’ve done this and you build your application you can include it in your yaml file
  4. Once you’ve generated a payload and programmed it to storage, when the HSS starts up it will configure the hardware and the copy the payload to its desired memory
  5. Once the payload copy is completed the owner harts of the payload (specified in the .yaml file) will jump to the start of the payload and start executing the code contained in it.

This basically gets you to this initialization code in the MPFS HAL which will initialize memory and then jump to main of the application.

I hope this has helped a bit, let me know if you need more detail :slight_smile:

1 Like

First, thank you for your reply!

Ok… that clarifies a few things…

A few questions:

  1. For each hart to have it’s own payload, I’d have to make a separate project for each one in SoftConsole so there are individual .ELF files for each one.

I suppose these projects would share a common root directory so they can be found easily when using the HSS Payload Generator and in the .YAML file it would look something like this:

<hart 1 project><Binaries>\hart1.elf
<hart 2 project><Binaries>\hart2.elf
<hart 3 project><Binaries>\hart3.elf
<hart 4 project><Binaries>\hart4.elf

Correct???

  1. When using the HSS Payload Generator the config.yaml file should be in the and the output.bin file once it’s generated will also be in the same directory?

  2. I’ve noticed in some of the examples there are source files such as:
    e51.c with a function “void e51(void)” rather than “void main(void)”
    and the same u54_1.c, u54_2.c, u54_3.c and u54_4.c

So is a “main()” function necessary or just a function titled the same as the hart? e.g.- void u54_1(void)

My assumption is if each hart’s software is in different projects then a main() function would be necessary, correct?

  1. For each hart to have it’s own payload, I’d have to make a separate project for each one in SoftConsole so there are individual .ELF files for each one.

Yes you’ll need a separate project for each one - you could be sneaky and do all of the individual applications (if they’re bare metal) in the same SoftConsole project and have them operate independently but this could be more confusing then just having individual projects.

  1. When using the HSS Payload Generator the config.yaml file should be in the and the output.bin file once it’s generated will also be in the same directory?

You can pass paths to the payload generator (I can’t remember off the top of my head but it should support full or relative paths) so if everythings in the same directory you could do:

$ ./hss-payload-generator -c config.yaml output.bin

(You can also use paths in the config.yaml file)

or if things are being stored elsewhere you could do:

$ ./hss-payload-generator -c /home/user/blah/config.yaml /home/user/blah/output.bin

paths in the .yaml are set when you define the payload:

**test/baremetal.elf**: {exec-addr: '0xB0000000', owner-hart: u54_3, priv-mode: prv_m, skip-opensbi: true}

So is a “main()” function necessary or just a function titled the same as the hart? e.g.- void u54_1(void)

The e51() and u54_x() functions are the equivalent to main - theres a webinar running through the system startup here its a bit out of date but still gets the key points across. Basically the main first hart will end up in system_startup.c and then if there are other harts in the payload it’ll wake them up and then they’ll jump to the functions named after them based on their hart ID and so will the main first hart.

My assumption is if each hart’s software is in different projects then a main() function would be necessary, correct?

You should really be ok to just use the functions named after each hart (even if you just use 1) as they’ll check their hart ID and then jump to that function. You could put in a main if you want but you’d have to jump to it from the U54_x function or link it in place of the U54_x function.

Thank you!

That explains a lot and I’ll check out the webinar too.

I’ve been away for a little while. The Windows/Linux (dual boot) laptop I had died on me. It was only 2 years old… I usually use MacOS… so I had to buy another laptop.

This one has Windows 11.

Anyway I have a question…

I can generate the output.bin file using the HSS Payload Generator.

However in the videos it doesn’t explain how the output.bin file is programmed into the MPFS???

I also seem to have some other problems with the HSS upon startup but I already found another post ( Err about boot from emmc ) which covers some of the same problems I’m seeing (e.g. - it stops at [4.607346] HSS_MMCInit(): Attempting to select SDCARD … [0 )

Hi @MisterHemi

Re the programming of the .bin file, we recommend using USBImager to do this - the steps in this doc say they’re the linux content update, but its the same for programming any payload.

On the HSS issue, are you using the latest version of the Icicle Kit Reference Design (currently its 2022.09) which includes the HSS and seeing these issues? Could you verify J34, J35 and J43 are set correctly, theres a table and image showing their locations here.

I’m going to try to update the reference design. I think it may not be the latest.

I did set the jumpers according to the document but it’s still having the same problem.

Ok… I corrected the jumper settings. I also read through the Linux instructions and was able to load the bare metal project I created but it had many errors.

The problem now is that after I corrected some errors and tried running the HSS Payload Generator again Windows 11 is telling me that the software isn’t compatible.

So… i’m trying to figure out why it suddenly says that. I worked a little while earlier. Strange.

Ok cool, sounds like some good progress so far! I only have a windows 10 machine so I can’t test windows 11 compatibility issues unfortunately - usually I would run the payload generator in WSL if I’m on the Windows machine as its more convenient, if you still have windows 11 issues it may be a solution?

I’m not familiar with WSL, I think lol

Ok… I know what it is… but didn’t know the name.

This is WSL:

I also have most of the tools installed on that laptop (it dual boots between Windows 11 and Linux Mint) on Linux Mint. I could try using Linux if Windows continues to be a problem.

Cool, yes that is what I meant by WSL, sorry I’m too used to using the acronym :stuck_out_tongue:

Sounds like a plan so! We’ll test it out on a Windows 11 machine as well and see if we can reproduce the issue.

I learned what’s causing the HSS Payload Generator to not run on Windows 11.

I don’t think the problem is necessarily specific to Windows 11.

I downloaded the Hart Software Services repository from GitHub and it was placed in a GitHub folder.

If I try to run the HSS Payload Generator from that folder it won’t allow it. However after copying the contents into another folder (not within the GitHub folder) it works fine.

I only had some problems which were caused by the config.yaml file. That error would cause the HSS Payload Generator ro report this message:

yaml_parser_parse(): no error

When it reports that message it won’t generate the output.bin file
I edited the config.yaml payload statement and it works fine now.

I was trying to configure it to load the same payload into harts 1 through 4 but apparently I don’t quite understand that yet.

So I just reverted back to loading the payload into only 1 hart.

I did notice this example in the payloads repository polarfire-soc-amp-examples:

payloads:
  ../mpfs-rpmsg-bm/Master-Default/mpfs-rpmsg-master.elf: {exec-addr: '0x1000000000', owner-hart: u54_1, priv-mode: prv_m, skip-opensbi: true}
  ../mpfs-rpmsg-bm/Remote-Default/mpfs-rpmsg-remote.elf: {exec-addr: '0x1075BB0000', owner-hart: u54_4, priv-mode: prv_m, skip-opensbi: true}

So I need to figure out how to configure my payload(s) similar to that.

I have another question, it’s regarding the mapping of the I/O.
For example if I want to turn on LED1 which is attached (indirectly) to the pin labeled HSIO90PB0 on the PolarFire SoC.

I understand the LEDs and switches are attached to Bank 0

If I use the function MSS_GPIO_set_output() what would be the GPIO and PORT ID for HSIO90PB0?

Is there a table somewhere that explains the mapping?

void MSS_GPIO_set_output
(
    GPIO_TypeDef *      gpio,
    mss_gpio_id_t       port_id,
    uint8_t             value
);

Yes there is a table in the readme of the reference design here :slight_smile:

Hi Hugh,

This is kinda off topic but do you know if there’s bill of materials available for the Icicle Kit?

I had the board setup and left it. I believe someone bumped into things and one micro USB connector was ripped completely off of the board and another was damaged.

I’m not sure if one is repairable or not… it’s the one for programming the eMMC
and the other is the one for the UARTS, it can be easily repaired and I do have a hot air station.

It’s a major setback for me as I was very determined to get everything going very soon.
I’m frustrated, to say the least.

Hi @MisterHemi

yes the BoM is available on the product page - this is the direct link to the file download

Thank you once again Hugh, I appreciate that!

I’m back… I managed to acquire a new development board, unfortunately the previous one is too difficult to repair.

I was having problems with my own code and decided to try one of the examples.

I verified the jumpers were set correctly and updated it to the latest reference design using Libero and the script.

After powering up the board and pressing a key to get a command prompt in the HSS when I entered “mcc” at the command prompt it says command not found.

However if I entered the command “usbdmsc” it would connect as a USB MSD and seems by default to select the mmc.

I attempted to run the example mpfs-timer-example

I used the config.yaml in that directory with the project.

After using USB Image Writer to load the output.bin file into the mmc I cycled the power on the board and watched the terminal screens (Cool Term) for uarts 1 and 2.

UART1:

.[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m
.[0m .[0m .[0m .[48;5;210m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m
.[0m .[0m .[0m .[0m .[48;5;217m .[48;5;203m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;196m .[48;5;203m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m .[0m
.[32m[6.35102].[33m HSS_E51_Banner(): .[1;32mPolarFire(R) SoC Hart Software Services (HSS) - version 0.99.29-dev-build
MPFS HAL version 1.8.140 / Mi-V IHC version 0.1.1
(c) Copyright 2017-2021 Microchip FPGA Embedded Systems Solutions.

.[0m.[32m[6.56368].[33m HSS_E51_Banner(): .[1;32mincorporating OpenSBI - version 0.9
(c) Copyright 2019-2021 Western Digital Corporation.

.[0m.[32m[6.68693].[33m HSS_PrintBuildId(): .[1;32mBuild ID: .[0m603c08ce3fe5cb84828deaf1f6587d85c7c879a7
.[32m[6.77634].[33m HSS_PrintToolVersions(): .[1;32mBuilt with the following tools:
.[0m - riscv64-unknown-elf-gcc (xPack GNU RISC-V Embedded GCC (Microsemi SoftConsole build), 64-bit) 8.3.0
 - GNU ld (xPack GNU RISC-V Embedded GCC (Microsemi SoftConsole build), 64-bit) 2.32

.[32m[6.102024].[33m HSS_E51_Banner(): .[1;33mNOTICE: Running from L2 Scratchpad

.[0m.[32m[6.109663].[33m Device_Serial_Number_Init(): .[1;32mSerial Number: 
.[0m9b75e211370d5e1ec6f873462bef46b200000000000000000000000000000000000000000000000000000000000000000000
.[32m[6.125287].[33m HSS_DDRPrintSegConfig(): .[1;32mSegment Configuration:
.[0m        Cached: SEG0_0: offset 0x0080000000, physical DDR 0x00000000
        Cached: SEG0_1: offset 0x1000000000, physical DDR 0x02000000
    Non-cached: SEG1_2: offset 0x00c0000000, physical DDR 0x78000000
Non-cached WCB: SEG1_4: offset 0x00d0000000, physical DDR 0x78000000
.[32m[6.156622].[33m HSS_DDRPrintL2CacheWaysConfig(): .[1;32mL2 Cache Configuration:
.[0m    L2-Scratchpad:  4 ways (512 KiB)
         L2-Cache:  8 ways (1024 KiB)
           L2-LIM:  4 ways (512 KiB)
.[32m[6.174416].[33m HSS_MemTestDDRFast(): .[0mDDR-Lo size is 32 MiB
.[0m.[32m[6.180839].[33m HSS_MemTestDDRFast(): .[0mDDR-Hi size is 1888 MiB
.[0m.[32m[6.187436].[33m HSS_BoardLateInit(): .[1;33mPlease ensure that jumpers J34/J43 are correct for 1.8V MMC voltage... 
.[0m.[32m[6.198373].[33m HSS_MMCInit(): .[1;32mAttempting to select SDCARD ... .[0mFailed
.[32m[7.207518].[33m HSS_MMCInit(): .[1;32mAttempting to select eMMC ... .[0mPassed
Press a key to enter CLI, ESC to skip
Timeout in 1 second
..
.[32m[9.514367].[33m HSS_TinyCLI_Parser(): .[0mCLI boot interrupt timeout
.[0m.[32m[9.521224].[33m HSS_IHCInit(): .[0mInitializing Mi-V IHC
.[0m.[32m[9.527040].[33m IPI_QueuesInit(): .[0mInitializing IPI Queues (6056 bytes @ 0xa035e88)...
.[0m.[32m[9.535720].[33m HSS_PMP_Init(): .[0mInitializing PMPs
.[0m.[32m[9.541275].[33m HSS_BootInit(): .[0mInitializing Boot Image..
.[0m.[32m[9.547524].[33m getBootImageFromMMC_(): .[0mPreparing to copy from MMC to DDR ...
.[0m.[32m[9.556335].[33m GPT_ValidateHeader(): .[1;31mGPT signature not as expected
.[0m.[32m[9.563713].[33m getBootImageFromMMC_(): .[1;31mGPT_PartitionIdToLBAOffset() failed - using offset 0
.[0m.[32m[9.573261].[33m getBootImageFromMMC_(): .[0mAttempting to read image header (1632 bytes) ...
.[0m.[32m[9.587253].[33m copyBootImageToDDR_(): .[0mCopying 68536 bytes to 0xa0000000
.[0m.[32m[9.598736].[33m HSS_BootInit(): .[1;32mBoot image passed CRC
.[0m.[32m[9.604899].[33m HSS_BootInit(): .[0mBoot image set name: "PolarFire-SoC-HSS::TestImage"
.[0m.[32m[9.613406].[33m HSS_BootInit(): .[0mBoot Image registered...
.[0m.[32m[9.619568].[33m HSS_Boot_RestartCore(): .[0mcalled for all harts
.[0m.[32m[9.626078].[33m HSS_Wdog_MonitorHart(): .[0mmonitoring .[0mU54_1 U54_2 U54_3 U54_4
.[32m[9.633804].[33m RunStateMachine(): .[1;34mipi_poll_service :: Init -> Monitoring
.[0m.[32m[9.641702].[33m boot_init_handler(): .[1;32mboot_service(u54_1):: BOOT_FLAG_SKIP_OPENSBI found
.[0m.[32m[9.650816].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: Init -> SetupPMP
.[0m.[32m[9.658802].[33m RunStateMachine(): .[1;34mboot_service(u54_2) :: Init -> SetupPMP
.[0m.[32m[9.666788].[33m RunStateMachine(): .[1;34mboot_service(u54_3) :: Init -> SetupPMP
.[0m.[32m[9.674773].[33m RunStateMachine(): .[1;34mboot_service(u54_4) :: Init -> SetupPMP
.[0m.[32m[9.682759].[33m RunStateMachine(): .[1;34musbdmsc_service :: Init -> Idle
.[0m.[32m[9.690050].[33m RunStateMachine(): .[1;34mbeu_service :: init -> monitoring
.[0m.[32m[9.697515].[33m RunStateMachines(): .[1;33m loop 1 took 38226571 ticks (max 38226571 ticks)
.[0m.[32m[9.706473].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: SetupPMP -> SetupPMPComplete
.[0m.[32m[9.719441].[33m RunStateMachine(): .[1;34mboot_service(u54_2) :: SetupPMP -> SetupPMPComplete
.[0m.[32m[9.728468].[33m RunStateMachine(): .[1;34mboot_service(u54_3) :: SetupPMP -> SetupPMPComplete
.[0m.[32m[9.737495].[33m RunStateMachine(): .[1;34mboot_service(u54_4) :: SetupPMP -> SetupPMPComplete
.[0m>> .[32m[9.746783].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: SetupPMPComplete -> ZeroInit
.[0m.[32m[9.755810].[33m RunStateMachine(): .[1;34mboot_service(u54_2) :: SetupPMPComplete -> ZeroInit
.[0m.[32m[9.764837].[33m RunStateMachine(): .[1;34mboot_service(u54_3) :: SetupPMPComplete -> ZeroInit
.[0m.[32m[9.773864].[33m RunStateMachine(): .[1;34mboot_service(u54_4) :: SetupPMPComplete -> ZeroInit
.[0m.[32m[9.783230].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: ZeroInit -> Download
.[0m.[32m[9.791563].[33m RunStateMachine(): .[1;34mboot_service(u54_2) :: ZeroInit -> Download
.[0m.[32m[9.799895].[33m RunStateMachine(): .[1;34mboot_service(u54_3) :: ZeroInit -> Download
.[0m.[32m[9.808228].[33m RunStateMachine(): .[1;34mboot_service(u54_4) :: ZeroInit -> Download
.[0m.[32m[9.816561].[33m boot_download_chunks_onEntry(): .[0mboot_service(u54_1)::Processing boot image: "mpfs-timer-example.elf"
.[0m.[32m[9.827932].[33m RunStateMachine(): .[1;34mboot_service(u54_2) :: Download -> Idle
.[0m.[32m[9.835917].[33m RunStateMachine(): .[1;34mboot_service(u54_3) :: Download -> Idle
.[0m.[32m[9.843903].[33m RunStateMachine(): .[1;34mboot_service(u54_4) :: Download -> Idle
.[0m.[32m[9.856775].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: Download -> OpenSBIInit
.[0m.[32m[9.865369].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: OpenSBIInit -> Wait
.[0m.[32m[9.873615].[33m boot_opensbi_init_onExit(): .[0mboot_service(u54_1)::u54_1:goto 0x80000000
.[0m.[32m[9.882486].[33m boot_wait_onEntry(): .[0mboot_service(u54_1)::Checking for IPI ACKs: - -
.[0m.[32m[9.901703].[33m boot_wait_handler(): .[0mboot_service(u54_1)::Checking for IPI ACKs: ACK/IDLE ACK
.[0m.[32m[9.957030].[33m RunStateMachine(): .[1;34mboot_service(u54_1) :: Wait -> Idle
.[0m.[32m[10.09665].[33m RunStateMachines(): .[1;33m loop 278 took 74891354 ticks (max 74891354 ticks)
.[0m.[32m[55.363281].[33m RunStateMachines(): .[1;32m loop 2500000 took 11044 ticks (max 74891354 ticks)
.[0m.[32m[100.714649].[33m RunStateMachines(): .[1;32m loop 5000000 took 11022 ticks (max 74891354 ticks)

However I get an error message
UART2:

.[32m[9.706637].[33m HSS_Boot_PMPSetupHandler(): .[0mHart1 .[0msetup complete
.[32m[9.882650].[33m HSS_GOTO_IPIHandler(): .[0mAddress to execute is 0x80000000
.[0msbi_trap_error: hart1: illegal instruction handler failed (error -2)
sbi_trap_error: hart1: mcause=0x0000000000000002 mtval=0x000000000000aaaa
sbi_trap_error: hart1: mepc=0x0000000080000000 mstatus=0x0000000a00001800
sbi_trap_error: hart1: ra=0x000000000a00c752 sp=0x000000000a041da8
sbi_trap_error: hart1: gp=0x0000000000000000 tp=0x000000000a027df0
sbi_trap_error: hart1: s0=0x0000000a00001800 s1=0x0000000000000003
sbi_trap_error: hart1: a0=0x0000000000000001 a1=0x0000000000000000
sbi_trap_error: hart1: a2=0x0000000000000007 a3=0x0000000000000019
sbi_trap_error: hart1: a4=0x0000000000000000 a5=0x0000000000000001
sbi_trap_error: hart1: a6=0x0000000000000010 a7=0x0000000000000010
sbi_trap_error: hart1: s2=0x0000000a00001800 s3=0x0000000080000000
sbi_trap_error: hart1: s4=0x0000000000000000 s5=0x0000000000000001
sbi_trap_error: hart1: s6=0x0000000000000000 s7=0x000000000a01daf0
sbi_trap_error: hart1: s8=0x000000000a021cf0 s9=0x0000000000000000
sbi_trap_error: hart1: s10=0x0000000000000000 s11=0x0000000000000000
sbi_trap_error: hart1: t0=0x0000000a00001880 t1=0x000000000a008c10
sbi_trap_error: hart1: t2=0x0000000000000001 t3=0x0000000000000011
sbi_trap_error: hart1: t4=0x0000000000000000 t5=0x0000000000000000
sbi_trap_error: hart1: t6=0x0000000000000000

I don’t know the reason(s) why these error occur.