- Introduction
On PolarFire SoC, auto update and In-Application Programming (IAP) are the mechanisms through which the FPGA can reprogram itself. In auto update, the device reprograms itself on power-up, and in IAP, the device is programmed when an application executing on the device requests it. In both cases, the system controller fetches a bitstream from external SPI flash & uses that to program the device.
Unlike other SoC FPGAs that support reprogramming from Linux, PolarFire SoC is a flash-based FPGA, and does not support partial reconfiguration. As a result, reprogramming the FPGA requires disabling both the FPGA fabric & the Microprocessor Subsystem (MSS). If reprogramming is initiated, the device is halted and a device reset occurs, whether the re-programming has been successful or not.
Since Linux runs on the MSS, initiating IAP would immediately take the system down, without going through the proper Linux shutdown procedure. If other operations were in progress, they would be immediately killed, which may be problematic. Auto Update only runs on power-up, avoiding issues shutting Linux down gracefully. For this reason, the officially supported option for reprogramming from Linux is auto update.
The auto update feature is not enabled by default and needs to be enabled using Libero SoC. The Bitstream Requirements for Auto Update section describes the steps required to enable and configure auto update using Libero. Alternatively, from v2023.06 release, reference design assets with auto update support are provided as part of the PolarFire SoC Video Kit Reference Design Releases.
Before attempting to run auto update, make sure you have a board with a PolarFire SoC device with production silicon, such as the PolarFire SoC Video Kit (MPFS250-VIDEO-KIT).
Icicle Kits with Engineering Sample silicon (denoted as -es) are not able to write to the flash from the MSS. As such, IAP and auto update are not supported.
In order to use auto update, or IAP for that matter, some consideration must be made when designing a board, as an external flash is used to store FPGA bitstreams, connected to the system controller. Please see the PolarFire SoC FPGA Programming User Guide for more information on this requirement.
The Hart Software Services (HSS) Kconfig option COLDREBOOT_TRY_AUTO_UPDATE
is required to support triggering auto update when a "reboot" command is issued in Linux.
Linux takes care of writing the FPGA bitstream to the SPI flash, so that on the
next power-up, an automatic update will take place.
In order to perform an auto update, some constraints apply for both the existing and the to-be-programmed bitstreams.
Firstly, auto update must be enabled in the existing bitstream.
-
Clone or download the latest PolarFire SoC Video Kit Reference Design
-
Open the latest Libero
-
Open the execute script dialog (CTRL + U)
-
Execute the "MPFS_VIDEO_KIT_REFERENCE_DESIGN.tcl" script
-
From the Design Flow window, double-click the "Generate FPGA Array Data" option and wait for the full process to finish
-
From the Design Flow window, double-click the "Configure Design Initialization Data and Memories" option. Select the SPI Flash tab and set the "Enable Auto Update" checkbox and then click the "Apply" button
It is possible to program an eNVM client which may be useful for upgrading the HSS. To add an eNVM client:
-
From the Design Flow window, double-click the "Configure Design Initialization Data and Memories" option. Select the "eNVM" tab
-
Click the "Add" button and then select "Add Boot Mode 1 Client" from the dropdown menu
-
Select the binary that should be programmed to the eNVM. In this case, we will select the Hart Software Services compiled using the PolarFire SoC Video Kit as the target board. The binary should be in Intel Hex format. Click the OK button
Note: The Hart Software Services release page on GitHub contains assets in Intel hex format that can be to program to the eNVM.
-
The eNVM tab should now show the eNVM client we just added in the step above. Click "Apply" to save the changes
-
From the Design Flow Window, double-click "Configure Programming Options"
-
The following dialog box should appear:
The Design version is a number between 0 and 65535. It specifies the Design version of the generated bitstream.
Back level protection blocks re-programming the FPGA with a bitstream older than that currently programmed. This is a security feature, disabled by default, that might be useful in a production environment. For more information please refer to the PolarFire SoC Programming User Guide.
-
In this case we will set the Design version to 23060 to indicate that the bitstream contains the 2023.06 PolarFire SoC Video Kit Reference Design release. Click "OK" to apply the changes
-
From the Design Flow Window, double-click the "Generate Bistream" option
The bitstream with auto-update enable is now generated. To program it to the device, a
.job
file is required. It will be exported in the next step. -
Export the design bitstream into a Job file. From the Design Flow Window, select "Export FlashPro Express Job"
Make sure you have selected the "Design" checkbox as shown in the image above.
Optionally, you can change the name and location of the output file. For demonstration purposes, we are going to name it
VKPFSOC_TOP_DESIGN
and leave the default output directory. The default output directory ispolarfire-soc-video-kit-reference-design/VKPFSOC_H264/designer/VKPSOC_TOP/export
.
A golden image
needs to be present in the SPI flash in image index 0, address
0x100400, which will be used as a back-up if updating to the runtime supplied
image fails. The SPI Flash Layout section provides
additional information on the SPI descriptors and offsets required for
using auto update.
This section explains how to generate and configure a golden image using Libero:
-
From the Design Flow window, double-click the "Export Bistream" option. Select the SPI checkbox to generate a bitstream with a
spi
extension. Click "OK".Optionally, you can change the name and location of the output file. For demonstration purposes, we are going to name it
VKPFSOC_TOP.spi
and leave the dafault output directory. The default output directory ispolarfire-soc-video-kit-reference-design/VKPFSOC_H264/designer/VKPSOC_TOP/export
. -
Add the VKPFSOC_TOP.spi bitstream generated in step 1 above as a Golden/Recovery image. From the Design Flow window, double-click the Configure Design Initialization Data and Memories
-
Select the SPI Flash tab. Select Add -> Add a SPI bitstream Client
-
From the Add SPI Bistream client window, configure the following fields:
Name: For demonstration purposes, we are going to set the name to
mpfs_golden_image
Type: SPI Bistream file for Recovery/Golden
Start Address (HEX): 0x100400
The space before 0x100400 is ordinarily reserved for non-bitstream objects, such as dt-overlays. From 0x100400 to 0x3D00400 is reserved for FPGA images.
-
Click Ok and then select the "Apply" button to save the changes
-
From the Design Flow Window, double-click the "Generate Bitstream" option
The
.spi
image used as golden image has now been generated. To program it on the SPI flash, a.job
file is required. The later will be generated in the next step. -
Export the SPI Flash golden image to a Job File. From the Design Flow Window, select "Export FlashPro Express Job"
Make sure you uncheck the "Design" checbox and select the "SPI Flash" checkbox as shown in the image above.
Optionally, you can change the name and location of the output file. For demonstration purposes, we are going to name it
VKPFSOC_TOP_SPI
and leave the default output directory. The default output directory ispolarfire-soc-video-kit-reference-design/VKPFSOC_H264/designer/VKPSOC_TOP/export
.
In the previous section two FlashPro Express job files were generated, one containing the design and another one containing the SPI Flash golden image.
In this section, we will use FlashPro Express tool to program both Job Files to the Video Kit.
Before running the steps above make sure you connect the PC and the board using a standard micro-USB cable into the USB-JTAG J5 connector. For more information on FlashPro jumper settings please refer to the PolarFire SoC Video Kit User Guide.
-
Power on the Video Kit
-
Open FlashPro Express.
-
From the title bar select Project -> New Job Project
-
Import the FlashPro Express design job file
VKPFSOC_TOP_DESIGN.job
. -
Press the RUN button to program the design to the Video Kit. Wait for the process to finish
-
From the title bar select Project -> New Job Project to create a new project
-
Import the FlashPro Express SPI job file
VKPFSOC_TOP_SPI.job
-
Press the "RUN" button to program the golden image to the System Controller SPI Flash. Wait for the process to finish
Once both FlashPro Express Job files have been programmed, the Video Kit will be capable of supporting auto update.
The system controller's QSPI & the attached flash must be present in the DeviceTree. An example DeviceTree configuration would look like:
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
ranges;
mbox: mailbox@37020000 {
compatible = "microchip,mpfs-mailbox";
reg = <0x0 0x37020000 0x0 0x58>, <0x0 0x2000318C 0x0 0x40>,
<0x0 0x37020800 0x0 0x100>;
interrupt-parent = <&plic>;
interrupts = <96>;
#mbox-cells = <1>;
status = "okay";
};
syscontroller_qspi: spi@37020100 {
compatible = "microchip,mpfs-qspi", "microchip,coreqspi-rtl-v2";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x37020100 0x0 0x100>;
interrupt-parent = <&plic>;
interrupts = <110>;
clocks = <&scbclk>;
status = "okay";
sys_ctrl_flash: flash@0 { // MT25QL01GBBB8ESF-0SIT
compatible = "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <20000000>;
spi-rx-bus-width = <1>;
reg = <0>;
};
};
};
syscontroller: syscontroller {
compatible = "microchip,mpfs-sys-controller";
mboxes = <&mbox 0>;
microchip,bitstream-flash = <&sys_ctrl_flash>;
status = "okay";
};
All required options are configured in the PolarFire SoC Video Kit device tree, used as the basis of PolarFire SoC's support in our Yocto BSP & Buildroot.
The auto update driver and dependencies must be enabled. If using a release prior to v2024.06, and therefore the linux-6.1-mchp+fpga kernel, the required options are:
CONFIG_FPGA=y
CONFIG_FPGA_BRIDGE=y
CONFIG_FPGA_REGION=y
CONFIG_FPGA_MGR_MICROCHIP_AUTO_UPDATE=y
CONFIG_FPGA_MGR_MICROCHIP_SPI=y
CONFIG_DEBUG_FS=y
For v2024.06 and later releases the driver and interface has changed.
CONFIG_FW_UPLOAD=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_POLARFIRE_SOC_AUTO_UPDATE=y
All required options are set in mpfs_defconfig, used as the basis of PolarFire SoC's support in our Yocto BSP & Buildroot.
Before performing an auto update in Linux, you'll need:
-
A bitstream that supports auto update programmed to the device. This can be achieved by following the
Bitstream Requirements for Auto Update
section in this document. Alternatively, if using the PolarFire SoC Video Kit, reference design release assets can be used instead (v2023.06 reference design or higher) -
A bitstream with a
.spi
file extension which contains a design version higher than the design version programmed in the device. For examplefoo.spi
.
After upstreaming the driver to mainline Linux, the interface changed and no longer uses debugfs. The steps here differ depending on whether a release prior to v2024.06 is in use or not, with the final portion being common.
The bitstream to be programmed must be placed in /lib/firmware
, named mpfs_bitstream.spi
.
Several methods can be used to place the foo.spi
image into the Linux file system such as
USB OTG in host mode (J19 on video kit with J57 and J18 closed) or Ethernet (RJ45 connector J7)
root@mpfs-video-kit:~# mkdir -p /lib/firmware
root@mpfs-video-kit:~# cp foo.spi /lib/firmware/mpfs_bitstream.spi
Write a 1
to /sys/kernel/debug/fpga/microchip_exec_update
, for example:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
If successful, the console should display some messages indicating that the bistream image has been transferred to the SPI flash and the bitstream address has been copied to the spi flash directory. For more information on the SPI flash memory layout please refer to the SPI Directory Layout section. Finally, the system controller reads the bitstream from the SPI flash to verify its content.
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[ 109.173410] fpga_manager fpga0: writing mpfs_bitstream.spi to Microchip MPFS Auto Update FPGA Manager
[ 109.293877] mpfs-auto-update mpfs-auto-update: Writing the image address (1500400) to the flash directory (4)
[ 109.314809] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (1500400)
[ 147.676660] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (1500400)
[ 172.018172] mpfs-auto-update mpfs-auto-update: Running verification of Update Image
[ 176.746100] mpfs-auto-update mpfs-auto-update: Verification of Update Image passed!
In these releases we make use of the Firmware Upload API provided by the Linux kernel to write the bitstream to the device.
Start by copying the bitstream to the device.
Several methods can be used to place the foo.spi
image into the Linux file system such as
USB OTG in host mode (J19 on video kit with J57 and J18 closed) or Ethernet (RJ45 connector J7)
Start the upload process by writing "1" to the loading file. Then write the bitstream into the data file.
root@mpfs-video-kit:~# echo 1 > /sys/class/firmware/mpfs-auto-update/loading
root@mpfs-video-kit:~# cat fw_f.spi > /sys/class/firmware/mpfs-auto-update/data
Finally write a "0" to the loading file to begin copying the bitstream to the system controller's flash.
root@mpfs-video-kit:~# echo 0 > /sys/class/firmware/mpfs-auto-update/loading
If successful, the console should display some messages indicating that the bistream image has been transferred to the SPI flash and the bitstream address has been copied to the spi flash directory. For more information on the SPI flash memory layout please refer to the SPI Directory Layout section. Finally, the system controller reads the bitstream from the SPI flash to verify its content.
root@mpfs-video-kit:~# echo 0 > /sys/class/firmware/mpfs-auto-update/loading
[ 1406.107274] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (0x1500400)
[ 1414.275359] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (0x1500400)
[ 1421.669156] mpfs-auto-update mpfs-auto-update: Wrote 0x227830 bytes to the flash
[ 1421.677115] mpfs-auto-update mpfs-auto-update: Running verification of Upgrade Image
[ 1423.007712] mpfs-auto-update mpfs-auto-update: Verification of Upgrade Image passed!
In v2024.06 and later releases, it is possible to use the same interface and procedures to update any design info stored in the SPI flash. This data uses the following format to store several Devicetree overlays, with support for multiple contexts.
Address | Size (bytes) | Field Name | Description |
---|---|---|---|
0x0 | 4 | Magic value | Characters "M", "C", "H", "P" |
0x4 | 4 | Descriptor Length | 12 + 4 * #contexts |
0x8 | 2 | Info Format Version | Set to 0 for this revision |
0xA | 2 | Number of AMP contexts | |
0xC + 4 * N | 4 | Start address of dtbo struct context N |
Each context has an individual header/table, pointed to by the "Start address of dtbo struct context N" field in the Main Header. "dtbo" here is the common shorthand for Devicetree overlay blob files, derived from the file extension.
Offset | Size (bytes) | Field Name | Description |
---|---|---|---|
0x0 | 4 | Number of dtbos in this context | |
0x4 + 12 * M | 4 | Start address of Mth dtbo | |
0x8 + 12 * M | 4 | End address of Mth dtbo | |
0xC + 12 * M | 4 | Size of Mth dtbo |
The Design Info is written to the SPI flash in the same way as the image itself:
root@mpfs-video-kit:~# echo 1 > /sys/class/firmware/mpfs-auto-update/loading
root@mpfs-video-kit:~# cat design_info.spi > /sys/class/firmware/mpfs-auto-update/data
root@mpfs-video-kit:~# echo 0 > /sys/class/firmware/mpfs-auto-update/loading
[ 281.201780] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (0x400)
[ 281.452358] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (0x400)
[ 281.472072] mpfs-auto-update mpfs-auto-update: Wrote 0xbcc bytes to the flash
If verification passes, type reboot
to initiate the re-programming:
root@mpfs-video-kit:~# reboot
Once the reboot command gets issued, the system controller reads the bitstream image from the SPI flash and programs the design into the device. The following message should be displayed in the terminal to indicate that the auto update is in progress.
...
[ 214.968630] reboot: Restarting system
[232.748680] reboot: Auto Update in progress
After a short delay, the HSS will start up and the new design should have been programmed to the device.
There are cases were writing the image to the flash or doing the auto update may fail.
The following error is likely to occur if there is no bitstream named
mpfs_bistream.spi
in the /lib/firmware directory:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[ 56.441509] fpga_manager fpga0: writing mpfs_bitstream.spi to Microchip MPFS Auto Update FPGA Manager
[ 56.450992] fpga_manager fpga0: Direct firmware load for mpfs_bitstream.spi failed with error -2
[ 56.459881] fpga_manager fpga0: Error requesting firmware mpfs_bitstream.spi
[ 56.467018] mpfs-auto-update mpfs-auto-update: Failed to write the bitstream
[ 56.474149] mpfs-auto-update mpfs-auto-update: error -ENOENT: Auto Update failed
The following error is likely to occur if the image exceeds the space available on the flash:
root@mpfs-video-kit:~# echo 0 > /sys/class/firmware/mpfs-auto-update/loading
[ 1819.027032] mpfs-auto-update mpfs-auto-update: flash device has insufficient capacity to store this bitstream
or with releases prior to v2024.06:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[73801.553485] fpga_manager fpga0: writing mpfs_bitstream.spi to Microchip MPFS Auto Update FPGA Manager
[73806.743402] mpfs-auto-update mpfs-auto-update: flash device has insufficient capacity to store this bitstream
[73806.753474] fpga_manager fpga0: Error while writing image data to FPGA
[73806.959995] mpfs-auto-update mpfs-auto-update: Failed to write the bitstream
[73806.967184] mpfs-auto-update mpfs-auto-update: error -EINVAL: Auto Update failed
In this other example, the driver failed to verify the image that was intended to be programmed. In this case, it is likely that the bitstream is invalid, ensure you have followed the steps in this document for the creation of a correctly formatted bitstream.
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[ 1962.080868] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (0x5f0400)
[ 1970.284324] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (0x5f0400)
[ 1977.727192] mpfs-auto-update mpfs-auto-update: Wrote 0x227830 bytes to the flash
[ 1977.735101] mpfs-auto-update mpfs-auto-update: Running verification of Upgrade Image
[ 1977.763514] mpfs-auto-update mpfs-auto-update: Verification of Upgrade Image failed!
or with releases prior to v2024.06:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[73944.021438] fpga_manager fpga0: writing mpfs_bitstream.spi to Microchip MPFS Auto Update FPGA Manager
[73944.061811] mpfs-auto-update mpfs-auto-update: Writing the image address (1500400) to the flash directory (4)
[73944.082790] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (1500400)
[73947.850574] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (1500400)
[73950.270617] mpfs-auto-update mpfs-auto-update: Running verification of Update Image
[73950.298524] mpfs-auto-update mpfs-auto-update: Verification of Update Image failed!
[73950.314199] fpga_manager fpga0: Error after writing image data to FPGA
[73950.321164] mpfs-auto-update mpfs-auto-update: Failed to write the bitstream
[73950.328294] mpfs-auto-update mpfs-auto-update: error -EBADMSG: Auto Update failed
The following message may be seen if the version of the bitstream being programmed is the same as that which is already programmed:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[ 1406.107274] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (0x1500400)
[ 1414.275359] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (0x1500400)
[ 1421.669156] mpfs-auto-update mpfs-auto-update: Wrote 0x227830 bytes to the flash
[ 1421.677115] mpfs-auto-update mpfs-auto-update: Running verification of Upgrade Image
[ 1423.007712] mpfs-auto-update mpfs-auto-update: Verification of Upgrade Image passed!
root@mpfs-video-kit:~# reboot
...
[76214.185933] reboot: Restarting system
[76232.88482] reboot: Auto Update image is not an update: 24
[76232.94498] reboot: Using fallback reboot provider
or with releases prior to v2024.06:
root@mpfs-video-kit:~# echo 1 > /sys/kernel/debug/fpga/microchip_exec_update
[6100.853425] fpga_manager fpga0: writing mpfs_bitstream.spi to Microchip MPFS Auto Update FPGA Manager
[76100.975527] mpfs-auto-update mpfs-auto-update: Writing the image address (1500400) to the flash directory (4)
[76100.996143] mpfs-auto-update mpfs-auto-update: Erasing the flash at address (1500400)
[76139.708658] mpfs-auto-update mpfs-auto-update: Writing the image to the flash at address (1500400)
[76164.008867] mpfs-auto-update mpfs-auto-update: Running verification of Update Image
[76168.736811] mpfs-auto-update mpfs-auto-update: Verification of Update Image passed!
root@mpfs-video-kit:~# reboot
...
[76214.185933] reboot: Restarting system
[76232.88482] reboot: Auto Update image is not an update: 24
[76232.94498] reboot: Using fallback reboot provider
The first 1 MiB after the SPI directory is reserved for carrying information about the bitstream, dt-overlays etc. It has no corresponding SPI directory.
|------------------------------| 0x0000000
| 1 KiB |
| SPI directory |
|------------------------------| 0x0000400
| 1 MiB |
| Reserved area |
| Used for bitstream info |
|------------------------------| 0x0100400
| 20 MiB |
| Golden Image |
|------------------------------| 0x1500400
| 20 MiB |
| Auto Update Image |
|------------------------------| 0x2900400
| 20 MiB |
| Reserved for multi-image IAP |
| Unused for Auto Update |
|------------------------------| 0x3D00400
| ? B |
| Unused |
|------------------------------| 0x?
The SPI directory is a collection of image descriptor pointers that point to the beginning of the programming image. For more information, please refer to section 10.2 of the PolarFire SoC FPGA Programming User Guide.
The SPI directory is laid out like so:
|------------------------------| 0x000
| Golden Image Address: |
| 0x0100400 |
|------------------------------| 0x004
| Update Image Address |
| 0x1500400 |
|------------------------------| 0x008
| Empty |
| 0x000000 |
|------------------------------| 0x00C
| Unused for re-programming |
| |
|------------------------------| 0x400