Skip to content

Latest commit

History

History
279 lines (202 loc) 路 16.2 KB

4_NIOS2HPS.md

File metadata and controls

279 lines (202 loc) 路 16.2 KB

Back to the startpage

Using the Intel NIOS II Soft-Core processor running FreeRTOS to interact with Hard Processor System (HPS) IP

Alt text

The following step-by-step guide demonstrate how to access Hard-IP, such as UART, of the ARM Cortex-A9 system with the Intel NIOS II processor running as Soft-IP inside the FPGA fabric. The microcontroller (MCU) executes the real-time operating system FreeRTOS. A task running on FreeRTOS can than be used to communicate with HPS Hard-IP. This Demo is written for an Intel Cyclone V SoC-FPGA on a Terasic DE10-Nano, DE10-Standard and DE0-Nano SoC.

Intel SoC-FPGAs, such as the Cyclone V, have a ARM AXI Interface between the HPS- and FPGA-part of the SoC to allow the FPGA to access almost the entire memory space of the ARM Cortex-A9 application processor system. This interface is called FPGA-to-HPS Bridge.

This includes for instance all Hard-IP modules, such as UART-,I虏C- or CAN-Bus and the on-chip memory used by the bootloader during boot. It is enabled to export the interrupt lines of the Hard-IP module to the FPGA fabric as well. This skill can bring the capability to the NIOS II processor to react for example to CAN-Packages via a CAN RX interrupt.

An additional microcontroller inside the SoC, running a real-time operating system, such as FreeRTOS, can rapidly extend the real-time related performance of an embedded Linux Distribution. Such a two processor solution can combine the benefits of a Linux- and real-time OS and it can be assumed that the real-time performance is significantly higher as a single processor solution with a real-time optimized Linux Kernel.

For my embedded Linux rsyocto I already wrote examples and guides that demonstrate the interaction between FPGA Soft-IP devices and embedded Linux. That can be assumed for the NIOS II to Linux communication as well.

This guide shows the second path of this two Processor solution: The design of a NIOS II Soft-Core processor that can use the HPS Hard-IP. The configuration of the NIOS II and the Bridge interface to the HPS is with Intel's Quartus Prime Platform Designer really straight forwards.

The most complicated part is the designing of all components beside. For example it is necessary to give after each boot the FPGA the privilege to access the address space of the HPS. Only the HPS can give these rights. That means a special optimized embedded Linux with an entire boot flow is necessary to achieve that.

Requirements of the final demo application

  • Configuration of the FPGA fabric with an Intel NIOS II Soft-Core Processor
  • Installment of FreeRTOS on the NIOS II Core
  • Configuration of the FPGA2HPS Bridge to allow the Hard-IP interaction with the NIOS II
  • Toggling the HPS_LED via a FreeRTOS Task
  • Reading the HPS_KEY via a external (EXTI) Interrupt with the NIOS II
  • Sending a UART ASCI String with the NIOS II core over the Hard-IP UART interface

Required steps to achieve this demo

  • On FPGA hardware side
    • HPS configuration with enabling of the FPGA-to-HPS-Bridge and assignment of Interrupt lines to the FPGA Fabric
    • NIOS II Soft-Core processor configuration with system memory
    • Connecting of the NIOS II AVALON Bus via an Address Expander to the FPGA-to-HPS-Bridge
    • Connecting of the NIOS II Interrupt controller to the IRQ Bridge to the exported HPS Interrupt lines
    • Connecting of a Soft-IP timer to NIOS II Avalon bus to give the FreeRTOS a system schedule systick timer interrupt
    • Connecting some FPGA-LEDs and FPGA-Switches to the NIOS II
  • On HPS software side
    • Using the u-boot boot script to enable give the FPGA the privileges to access the Hard-IP
    • It can alternatively be done via the usage of a Linux Shell start up script
    • Changing the Linux device tree to disable the loading of the Linux driver for the with NIOS II used modules
  • On NIOS II software side
    • Creating of an Eclipse for NIOS II project with FreeRTOS support
    • Writing some FreeRTOS tasks to communicate with the Hard-IP

The most complicated and time consuming part of this project is not the FPGA design, that is completely automated by Intel's Quartus Prime Platform Designer. Instead it is to design a bootflow for an embedded Linux to give the FPGA the privileges to access the HPS-Memory space and to instal the latest FreeRTOS version on the NIOS II processor.

To automate these two build steps I designed two Python scripts. To accomplish that I wrote a small library, called socfpgaHAL as a Hardware Abstraction layer (HPS) as a NIOS II driver for the Hard IP modules.

Installment of the required development tools

Follow the following instructions to install the required development tools:

  • Intel Quartus Prime Lite for Windows and Linux
    • with Eclipse for NIOS II support
  • Intel Embedded Development Suite (SoC EDS) 20.1 for Linux

Design of the required SoC-FPGA Platform

Finished Quartus Prime projects are available inside this Github repository.

The NIOS II Soft-Core processor can be designed as usually and will for that reason not mentioned in detail. Only the necessary application specific points will be shown here:

  • Necessary points to run the real-time OS FreeRTOS on a NIOS II Core
    • Interval Timer Intel FPGA as systick source for FreeRTOS
      • Name: sys_clk
      • Period: 1ms
      • Counter Size: 32
      • No Start/Stop control bit: YES
      • Interrupt line with the lowest priority (priority level 0) to the NIOS II Interrupt Controller
    • Required system memory space: ~250K Byte
  • Necessary points to connect the NIOS II Core with the HPS
    • Enable the FPGA-to-HPS interface

    • FPGA-to-HPS width: 32-bit

    • Enable the HPS-to-FPGA Interrupt line for the modules

    • Use an Address Span Expander to allow the NIOS II with its memory to interact with the 32-bit address size of the HPS

      • Due to the fact that the NIOS II requires some system memory the available address bus is too small

      • By using a sub-window offset of 0xfc000000 it is for the NIOS II Core enabled to access the entire memory space of the HPS components

      • That means a NIOS II Core can for example access the base address of CAN0 (HPS base Address: 0xFFC00000) by using the address 0x3C00000 (=0xFFC00000-0xFFC00000)

      • Use the following settings for the Address Span Expander

        Alt text

    • Connect the NIOS II AVALON Bus to the Window Slave Port of the Address Span Expander

    • Connect the FPGA-to-HPS Bridge of the HPS module to the expander master port of the Address Span Expander

  • Necessary points to connect HPS Interrupt lines to the NIOS II Core
    • Use an Interrupt Bridge module
      • To allow to use different clock domains between the NIOS II core and the HPS
      • Connect exported HPS-to-FPGA Interrupt lines with the Interrupt Receiver port of the Interrupt Bridge module

The following table illustrates the by the NIOS II accessible memory space with this configuration:

Alt text

Using an u-boot boot script or a Linux Shell script to give the NIOS II Core the privilege to access HPS memory space

Every module of the HPS has its own privilege bit. Only in the case this bit is set, it is for the FPGA part possible to access the depending peripheral component. The documentation of these registers are available inside the Intel Cyclone V Hard Processor System Technical Reference Manual (Link).

For instance to enable the UART1 component it is necessary to set the bit number 7 of the register l4sp (HPS Address 0xFF80000C). Alt text

As mentioned it is only for the HPS is it possible to change these registers and it must be done after every power up of the SoC-FPGA. To achieve that two suitable solutions are possible

  1. Setting the registers inside an u-boot script during boot
  2. Using a Linux Shell boot script

The first solutions is has the advantage to give the privilege instantly after the board is powered on. A major disadvantage is that complex boatload design is for adding an single u-boot command necessary. It will burn the most time for this project. However, with the build system of rsyocto based on the socfpgaPlatformGenerator can this be done in a few minutes.

For rsyocto-based Linux Distributions follow the customization guide and for general Intel SoC-FPGA can this guide be considered.

For example to give the NIOS II core the privilege to access the entire peripheral components add following to the u-boot script (socfpgaPlatformGenerator/ubootScript/uboot_cyclone5.script):

echo --- enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges ---
bridge enable;

echo --- enable FPGA2HPS peripherals access --

echo     for I2C,CAN,UART,TIM
mw.w 0xFF80000C 0x7FF
  
echo     for GPIO
mw.w 0xFF800010 0x3FC

echo     for OSC
mw.b 0xFF800014 0x60  

echo     for SPI
mw.b 0xFF800018 0x03

echo     for on-chip RAM
mw.b 0xFF800098 0x01

echo     Reset Bridges 
mw.b 0xFFD0501C 0x0  

Be sure that these commands are added after the FPGA configuration is written and the FPGA fabric was released from Reset. The mw.w u-boot command allows to write a word (32-bit) and the mw.b can write a byte (8-bit) to an address. After any change of the privilege set is nessary to released the Bridges from Reset. This must be done via the brgmodrst register (Address: 0xFFD0501C) by writing an "0".

Alternately it is also possible to change the registers with a Linux Shell script or just a single console command. For giving the NIOS II core the privilege to access the memory space of the I虏C-,CAN-,UART- and Timer run following command on the running embedded Linux:

devmem2 0xFF80000C w 0x7FF
devmem2 0xFFD0501C w 0

These two commands can also be inserted to a Linux Shell start up script as shown in the next example (e.g. for the DE10-Nano: socfpgaPlatformGenerator/Board_DE0NANOSOC/my_startUpScripts/startup_script.sh):

#!/bin/sh
# Startup script
# This script will be execute before the system starts the NIC
echo "rsYocto Startup script: started!"

echo "--- enable FPGA2HPS peripherals access --"
echo "   for I2C,CAN,UART,TIM"
devmem2 0xFF80000C w 0x7FF
echo "    Reset Bridges" 
devmem2 0xFFD0501C w 0

# Map RNG to the driver
RNGD_OPTS="-r /dev/random"
echo "Startup script: end!"

Change the Linux Device Tree to disable the loading of a with the NIOS II used component

To prevent the Linux Distribution to interact at same time as the NIOS II to a identical Hard-IP component disable it from the Linux device tree. Then this address space will not be used by the Linux Kernel and Kernel Mode drivers. For instance incase UART1 is used by the NIOS II Soft-Core processor disable the device for the embedded Linux. The following code shows the Linux device tree description for loading the driver for UART1 (serial1):

		serial1@ffc03000 {
			compatible = "snps,dw-apb-uart-16.1", "snps,dw-apb-uart";
			reg = <0xffc03000 0x1000>;
			interrupts = <0x0 0xa3 0x4>;
			reg-shift = <0x2>;
			reg-io-width = <0x4>;
			clocks = <0x29>;
			dmas = <0x34 0x1e 0x34 0x1f>;
			dma-names = "tx", "rx";
			phandle = <0x63>;
			status = "okay";
		};

A change of the status from "okay" to "disabled" will disable the loading of the driver for this device. Change for with NIOS II used peripheral component the status attributes to "disabled".

status = "disabled";

Booting the new designed Linux Distribution and configuring the FPGA fabric with the NIOS II Core

Use the build script as usual to generate a bootable image file with the changed bootflow. The Intel NIOS II Soft-Core processor is typically only in a demo mode (un-license) available. Intel Quartus Prime will reject to generate a binary FPGA configuration file with a NIOS II core. However, the build system will use for FPGA configuration a default file. That can be later overwritten.

Flash the output image file (.img) to a SD-Card and boot your development board with it as shown in the first guide.

After the complete boot of the embedded Linux is done connect the onboard ALTERA JTAG Blaster via an USB cable to your development computer. Write the FPGA configuration of your Quartus Prime project with the integrated debugger to the FPGA fabric of your development board.

Generating a NIOS II for Eclipse demo project with FreeRTOS and the HPS HAL lib

Another time consuming part of this project is usually to implement a real-time operating system (e.g. FreeRTOS) into an Eclipse project. I designed a Python script ("NIOSII_EclipseCompProject") to automate these steps, as well. It can clone the latest FreeRTOS version from Github and install an optimized port of it for the NIOS II processor. I wrote a small HAL library for accessing HPS IP with the NIOS II core. It can be pre-installed with custom user libraries, as well. The Python script will generate an Eclipse example project. That can be used as a reference for a further development.

Concept of the "NIOSII_EclipseCompProject" Python script:

Alt text

Follow the step-by-step guide of the script to generate the required project for this purpose.

Be sure, that you select inside the Python script the implementation of the socfpgaHAL as shown in the following screenshot: Alt text

Finish the generation of the Eclipse example project and then start Eclipse as described inside the documentation of the "NIOSII_EclipseCompProject".

Starting a new NIOS II for Eclipse debug session and running the example code

The starting of a new debug session is also shown inside the documentation of "NIOSII_EclipseCompProject" Github repository. Create a new Eclipse project that based on the NIOS II Software example "FreeRTOS+socfpgaHAL-robseb".

The project contains FreeRTOS implementation that accesses multiple Hard-IP components.

Understanding the socfpgaHAL Library

The "socfpgaHAL" is a small library that can be used as an HAL for interaction with HPS Hard-IP with a NIOS II processor.

The Structure of the "socfpgaHAL":

File Name Description
"socfpgaHAL.h" Main HAL file should only be used to include the HAL
"socfpgaHAL_config.h" The configuration file of the HAL

Use the configuration file to enable the access of components. For instance the GPIO support can be enabled by adding to the configuration file (socfpgaHAL/socfpgaHAL_config.h):

#define SOCFPGAHAL_ENABLE_GPIO 			(1)

Currently the support for the following Hard-IP components is available:

Peripheral Name Module Name Description
GPIO GPIO0, GPIO1, GPIO2 General-purpose I/O
Timer SPTIMER0, SPTIMER1, OSCTIMER0, OSCTIMER1 Timer
UART UART0, UART1, UART Soft-IP 16550 based Synopsys DesignWare APB Universal Asynchronous Receiver/Transmitter


Back to the startpage