PolarFire® SoC Applications - UART

Last modified by Microchip on 2026/10/08 11:03

Introduction

Universal Asynchronous Receiver/Transmitter (UART) is one of the most common interfaces for transmitting and receiving data. It is simple to use and requires only two signals, TX and RX, for asynchronous serial communication. On PolarFire® SoC devices, two UART interface types are available: the MSS UART peripherals in the Microprocessor Subsystem (MSS) and the fabric-based CoreUART.

This article focuses on using the MSS UART peripheral. It guides you through the required setup, programming the reference design, creating a bare-metal SoftConsole™ project, adding a simple UART transmit example, and verifying the output on the serial console. The article also covers the Yocto Project® workflow and demonstrates UART use in embedded Linux®.

Prerequisites

Hardware Setup

Software Setup

Additional Resources

Programming the Reference Design

To make the MSS UART peripheral available to software, enable the required UART peripherals in the MSS configurator. In the reference design, the UART peripherals are already enabled, and MSS MMUART_3 is routed to the USB-UART PHY. Before writing software, it is important to understand how the UART peripheral is connected on the target board.

The reference design also supports Yocto Linux, so the board-level UART connection should be checked against the corresponding reference design documentation. For this article, the PolarFire SoC Icicle Kit reference design is used.

MSS UART enabled in the MSS configuration

Icicle KitConnectionDiscovery KitConnection
MMUART_3 TXJ11 (Micro-USB)MMUART_3 TXJ4 (USB-C port)
MMUART_3 RXJ11 (Micro-USB)MMUART_3 RXJ4 (USB-C port)
Information

For more information about peripherals connection, refer to the board-specific reference design documentation:

Downloading the Reference Design

Open the latest release page for the PolarFire SoC Icicle Kit reference design:

https://github.com/polarfire-soc/icicle-kit-reference-design/releases

Download the PolarFire SoC Icicle Kit reference design generation FlashPro® images from the latest release.

Programming the FPGA Design

Open FlashPro Express.


Create a new project.


Select the reference design job file from the downloaded design package. Use the job file matching the following pattern:

MPFS_ICICLE_KIT_ES_*\MPFS_ICICLE_KIT_ES_BASE_DESIGN_*\MPFS_ICICLE_KIT_ES_*.job

Click Run to program the Field-Programmable Gate Array (FPGA).

Success

At this point, the FPGA fabric has been programmed with the reference design.

Warning

You have two programming options:

  1. Use the prebuilt reference programming files for a quick start.
  2. Build or modify the Libero SoC project and regenerate the programming file by following "PolarFire® SoC Applications - MSS and Libero SoC Design Suite".

Back to Top

UART in Linux® Environment

The UART peripheral must be enabled and configured in the Linux software configuration. That's why we need a Linux build system to configure it. For this article, we will use the Yocto Project.

Hart Software Services (HSS) Configurations

Hart Software Services (HSS) is the bootloader for PolarFire SoC. It runs first, sets up hardware, launches Linux or other apps, and is essential for multi-core and secure boot.

Objectives:

  • Download and import HSS to SoftConsole
  • Update references and build HSS
  • Deploy HSS to PolarFire Icicle Kit
Information

Note: This application article is verified on HSS 2025.07.

First, download HSS from GitHub®.


Import the HSS project to SoftConsole by going to File > Import > Import Existing Project Into Workspace.

Import Projects

Warning

Ensure that you checked Copy projects into workspace.

Browse the HSS folder and import the project into workspace by clicking Finish.


Copy your MSS XML file into the project.

Copy the XML file to hart-software-services/boards/mpfs-icicle-kit-es/soc_fpga_design/xml/<your xml>.xml.

Information

Note: If your board is a production board (not ES), use boards/mpfs-icicle-kit/... instead of boards/mpfs-icicle-kit-es/...


Copy and rename the HSS configuration file.

  1. Copy hart-software-services/boards/mpfs-icicle-kit-es/def_config to hart-software-services/.
  2. Rename def_config to .config.
  3. Edit .config file and update the path to your XML by changing the next line.
CONFIG_SOC_FPGA_DESIGN_XML="boards/mpfs-icicle-kit-es/soc_fpga_design/xml/<your xml>.xml"

Build HSS and deploy it to the device.

Right-click on the project name. 

Click on the build project. 

Select PolarFire SoC program non-secure boot mode 1 run option and deploy project to SoC. 

Warning

Make sure that the run configuration is correct. If necessary, open External Tools > External Tools Configurations and select the die and package that match your board. For the Icicle Kit ES, use die MPFS250T_ES and package FCVG484.

Back to Top

Yocto Project Configurations

In this section, we will create a Linux image and program it into the PolarFire SoC Icicle Kit.

Objectives:

  1. Setting up the Yocto Project building environment
  2. Enabling the UART peripheral and including the necessary packages in the build
  3. Building a Linux image and deploying it into the SoC

Creating Environment

To create the Linux build environment, refer to the "OpenEmbedded/Yocto Project BSP layer for Microchip's SoCs" page.

Configuring UART Peripheral

Prepare the Microchip Linux kernel (linux-mchp) source tree for local development:

MACHINE=mpfs-icicle-kit devtool modify linux-mchp
Success

We will get the following log:

Recipe linux-mchp now set up to build from /build/workspace/sources/linux-mchp


Add the required libraries and applications to the image.

Open the conf/local.conf file and add the following variable at the end of the file:

CORE_IMAGE_EXTRA_INSTALL += "packagegroup-core-buildessential vim"

Information
  • packagegroup-core-buildessential is a Yocto Project meta-package that pulls in all the essential build tools needed for compiling software on your embedded system.

    • Includes:

      • gcc → C compiler

      • make → build automation

      • binutils → linker, assembler, etc.

      • pkgconfig → helps locate libraries and headers

      • libc-dev → standard C library headers

      • autoconf, automake, libtool → for building autotools-based projects

  • vim is a powerful text editor used in terminal environments.

Save the file and exit.


Locate the board-specific DTS files and verify that the UART peripherals are configured:

yocto-dev/build/workspace/sources/linux-mchp/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
yocto-dev/build/workspace/sources/linux-mchp/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-common.dtsi

Make Sure that the uart0-3 are enabled in the DTS (in mpfs-icicle-kit-common.dtsi file):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
&uart0 {
    status = "okay";
};

&uart1 {
    status = "okay";
};

&uart2 {
    status = "okay";
};

&uart3 {
    status = "okay";
};

Compile a customized Yocto Project Linux kernel recipe in a developer-friendly way, producing kernel binaries for PolarFire SoC.

MACHINE=mpfs-icicle-kit devtool build linux-mchp
Warning

You can create a bbappend layer execute following command:

> devtool finish linux-mchp custom-layer

​​​​Your bbappend layer will be saved at: custom-layer/recipes-kernel/linux/linux-mchp_%.bbappend

Building Linux Image and Deploying

Execute the command shown below to build the Linux image:

MACHINE=mpfs-icicle-kit bitbake mchp-base-image

Here's the list of names of supporting machines. 

MACHINEBoard NameDescription
MACHINE=mpfs-icicle-kitMPFS-ICICLE-KIT-ES, MPFS-ICICLE-KITPolarFire SoC Icicle Kit
MACHINE=mpfs-disco-kitMPFS-DISCO-KITPolarFire SoC Discovery Kit
MACHINE=mpfs-video-kitMPFS250-VIDEO-KITPolarFire SoC Video Kit

After the build completes, you can locate your Linux image at:

yocto-dev/build/tmp-glibc/deploy/images/<board_name>/<image-name>.rootfs-***.wic


Follow the instructions in the "Programming a Linux Image" section to deploy the built image to the eMMC/SD card memory.

Information

For additional information, refer to the "OpenEmbedded/Yocto Project BSP layer for Microchip's SoCs" GitHub page.


After booting Linux on the PolarFire SoC Icicle board, log in as root and verify that the MSS UARTs and (if included in the FPGA design) the CoreUART peripheral appear as device nodes:

root@mpfs-icicle-kit:~# dmesg | grep -E "tty|serial" | grep MMIO
[    0.364873] 20100000.serial: ttyS1 at MMIO 0x20100000 (irq = 76, base_baud = 9375000) is a 16550A
[    1.945793] 20102000.serial: ttyS2 at MMIO 0x20102000 (irq = 77, base_baud = 9375000) is a 16550A
[    1.957332] 20104000.serial: ttyS3 at MMIO 0x20104000 (irq = 78, base_baud = 9375000) is a 16550A
[    1.968808] 20106000.serial: ttyS0 at MMIO 0x20106000 (irq = 79, base_baud = 9375000) is a 16550A
[    1.980031] 40000300.serial: ttyCOREUART5 at MMIO 0x40000300 (irq = 80, base_baud = 3125000) is a mchp_coreuart

If nothing returns, that means the UART device is not enabled and you have to double-check the configuration, DTS and driver modifications needed to be done.

Back to Top

Software

User-Space Application Development in C

We can write a C program that runs from user-space and interacts with UART devices. The following C program transmits data from a user-space application through a UART connected to a second serial console.

Boot Linux on your PolarFire SoC Icicle kit. Navigate to /media and create main.c using the vim editor:

cd /media && vim main.c

Copy and paste the following C code into main.c:

#include <stdio.h>
#include
<fcntl.h>
#include
<unistd.h>
#include
<termios.h>

int main() {
   // 1. Open the UART device in write-only mode
   int uart_fd = open("/dev/ttyS0", O_WRONLY | O_NOCTTY);
   if (uart_fd < 0) {
        perror("Failed to open UART");
       return 1;
    }

   // 2. Configure UART settings
   struct termios options;
    tcgetattr(uart_fd, &options);
    cfsetospeed(&options, B115200); // Set baud rate to 115200
   options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;     // No parity
   options.c_cflag &= ~CSTOPB;     // 1 Stop bit
   options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;         // 8 Data bits
   tcsetattr(uart_fd, TCSANOW, &options);

   // 3. Transmit data
   char tx_buffer[] = "Hello from C code!\r\n";
    write(uart_fd, tx_buffer, sizeof(tx_buffer) - 1);

   // 4. Clean up
   close(uart_fd);
   return 0;
}

After saving the modification, compile the C code on target:

gcc main.c -o main

Run the main executable:

./main
Success

The expected output is Hello from C code! on the other COM Port:

Expected Output

Back to Top

UART in Bare-Metal Applications

Building and Programming the SoftConsole™ Project

To use the MSS UART in the bare-metal side, we have to use the SoftConsole IDE to develop the application to build, compile and deploy.

For this application, let us take one of the GitHub bare-metal reference examples and change it so it uses the MSS UART to communicate with the host PC.

Download the mpfs-blank-baremetal bare metal application project from the repository on GitHub and import it into the SoftConsole.

Note: If this is your first time importing a project in SoftConsole, watch this video:


Replace the MSS Configuration XML file in the bare metal project with the XML file used in your Libero SoC Design Suite project. The path to the file that SoftConsole will use to generate header files, which are then used by the MPFS HAL, is:

mpfs-blank-baremetal > "your_board" > fpga_design > design_description > xx.xml

Replace its contents, or add the following application code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdint.h>
#include
"mpfs_hal/mss_hal.h"
#include
"drivers/mss/mss_mmuart/mss_uart.h"

#define DELAY_COUNTER_1S    129700000U
#define DELAY_COUNTER_1MS   (DELAY_COUNTER_1S / 1000U)
void delay_ms(uint64_t ms);
void delay(uint8_t seconds);


void u54_1(void){
    (void)mss_config_clk_rst(MSS_PERIPH_MMUART1, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);

    MSS_UART_init(&g_mss_uart1_lo,
                MSS_UART_115200_BAUD,
                (MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT));

   while(1u){
        MSS_UART_polled_tx_string(&g_mss_uart1_lo, "Hello !\r\n");
        delay(5);
    }
}

void delay_ms(uint64_t ms){
   for (uint64_t i = 0; i < (ms * DELAY_COUNTER_1MS); ++i) {
        __asm__("sll x0, x0, x0");
    }
}

void delay(uint8_t seconds){
    delay_ms(seconds * 1000);
}

Line 1-11: Include the integer, PolarFire SoC HAL, and MSS UART-driver definitions, and define the delay constants.

Line 12: The u54_1() function is the main entry point for the application.

Line 13-16: We initialize the UART peripheral.

Line 19: Sending the Hello ! message.

Line 20: Waiting 5 sec to repeat the message.

Line 24-32: Defining the delay functions.


Build the project and deploy it either in LIM for Debug mode or eNVM for Release mode.

Note: You can refer to this building and debugging bare metal applications in SoftConsole video.

Back to Top

Checking for the Results

Verify that the UART output works correctly by opening the serial connection and observing the transmitted message.

Open MobaXTerm and set up the serial connections for the available FlashPro UART ports.


Monitor the UART terminal and observe the transmitted message appearing every five seconds.


Confirm that the expected output is displayed in the terminal.

Expected Output

Success

If the setup is correct, the UART console displays the Hello ! message repeatedly at five-second intervals.

Back to Top

Summary

This article introduced the MSS UART peripheral on PolarFire SoC devices and showed how to use it in a bare-metal application. You reviewed the required hardware and software, programmed the PolarFire Icicle Kit reference design, created a SoftConsole project, enabled UART support, added a simple UART transmit application, and verified the output through a serial terminal.

The Yocto Linux UART usage path was identified as an additional option, but this article covered only the bare-metal flow supported by the provided material.

Back to Top