PolarFire® SoC Applications - UART
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
- This application is applicable to the following PolarFire SoC-based boards:
- PolarFire SoC Icicle Kit User Guide (the board used in this article)
- PolarFire SoC FPGA Discovery Kit User Guide
- PolarFire SoC - SoC Video Kit User Guide
- Three Micro-USB cables
- Logic analyzer (optional, for capturing UART transmission signals)
- Linux host PC for the Yocto Project build environment
Software Setup
- SoftConsole™ Integrated Development Environment (IDE)
- Libero® SoC Design Suite 2024.2+
- Yocto Project host environment
- Logic analyzer software, if a logic analyzer is used
- MobaXterm® for interactive serial-console access
Additional Resources
- Basics of UART Protocol
- PolarFire® SoC Applications - MSS and Libero SoC Design Suite
- PolarFire® SoC Applications - SoftConsole Integration
- PolarFire SoC Discovery Kit Reference Design
- PolarFire SoC Icicle Kit Reference Design
- PolarFire SoC Video Kit Reference Design
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.

| Icicle Kit | Connection | Discovery Kit | Connection |
|---|---|---|---|
| MMUART_3 TX | J11 (Micro-USB) | MMUART_3 TX | J4 (USB-C port) |
| MMUART_3 RX | J11 (Micro-USB) | MMUART_3 RX | J4 (USB-C port) |
Downloading the Reference Design
Open the latest release page for the PolarFire SoC Icicle Kit reference design:
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:
Click Run to program the Field-Programmable Gate Array (FPGA).
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
First, download HSS from GitHub®.
Import the HSS project to SoftConsole by going to File > Import > Import Existing Project 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.
Copy and rename the HSS configuration file.
- Copy hart-software-services/boards/mpfs-icicle-kit-es/def_config to hart-software-services/.
- Rename def_config to .config.
- Edit .config file and update the path to your XML by changing the next line.
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.
Yocto Project Configurations
In this section, we will create a Linux image and program it into the PolarFire SoC Icicle Kit.
Objectives:
- Setting up the Yocto Project building environment
- Enabling the UART peripheral and including the necessary packages in the build
- 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:
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"
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-common.dtsi
Make Sure that the uart0-3 are enabled in the DTS (in mpfs-icicle-kit-common.dtsi file):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.
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.
| MACHINE | Board Name | Description |
|---|---|---|
| MACHINE=mpfs-icicle-kit | MPFS-ICICLE-KIT-ES, MPFS-ICICLE-KIT | PolarFire SoC Icicle Kit |
| MACHINE=mpfs-disco-kit | MPFS-DISCO-KIT | PolarFire SoC Discovery Kit |
| MACHINE=mpfs-video-kit | MPFS250-VIDEO-KIT | PolarFire 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.
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:
[ 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.
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:
Copy and paste the following C code into main.c:
#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:
Run the main executable:
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.
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:
Replace its contents, or add the following application code:
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 "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.
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.

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.
