diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..a078858
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,2 @@
+@Library('automated-testing-library') _
+pipelineSoftIPExamples()
diff --git a/miv-rv32-udma/.cproject b/miv-rv32-udma/.cproject
new file mode 100644
index 0000000..015c247
--- /dev/null
+++ b/miv-rv32-udma/.cproject
@@ -0,0 +1,622 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miv-rv32-udma/.gitignore b/miv-rv32-udma/.gitignore
new file mode 100644
index 0000000..f8ed8bd
--- /dev/null
+++ b/miv-rv32-udma/.gitignore
@@ -0,0 +1,7 @@
+/*Debug*/
+/*Release*/
+/.settings*/
+/miv-rv32i-debug/
+/miv-rv32-imc-debug/
+/miv-rv32-imc-release/
+/miv-rv32i-release/
diff --git a/miv-rv32-udma/.project b/miv-rv32-udma/.project
new file mode 100644
index 0000000..0a46e7c
--- /dev/null
+++ b/miv-rv32-udma/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-udma
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/miv-rv32-udma/README.md b/miv-rv32-udma/README.md
new file mode 100644
index 0000000..e4351d3
--- /dev/null
+++ b/miv-rv32-udma/README.md
@@ -0,0 +1,58 @@
+# MIV uDMA Example
+
+This project demonstrates the Mi-V Soft IP uDMA module functionality, which is delivered as a
+part of MIV Extended Sub System(MIV_ESS).
+This project sets up the data transfer between two memory blocks, based on the
+configuration the uDMA controller will generate the interrupt for error or
+success of the transfer.
+The uDMA IRQ from the MIV_ESS can be connected to
+any of the external interrupt pins on the MIV_RV32, so the application
+developer should perform the interrupt handling in respective interrupt handler.
+
+
+There are 2 different build configurations provided with this project which configure
+this SoftConsole project for RISC-V IMC instruction extension.
+The Following configurations are provided with the example.
+ - miv32imc-Debug
+ - miv32imc-Release
+
+ To use this project, configure the COM port interface as below:
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control
+
+## fpga_design_config (formerly known as hw_config.h)
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. Detailed description of the folder structure is available
+at https://github.com/Mi-V-Soft-RISC-V/miv-rv32-documentation.
+The fpga_design_config.h must be stored as shown below
+
+`
+ /boards//fpga_design_config/fpga_design_config.h
+`
+
+Currently, this file must be hand crafted when using the Mi-V Soft Processor.
+In future, all the design and soft IP configurations will be automatically
+generated from the Libero design description data.
+
+You can use the sample file provided with MIV_RV32 HAL as an example.
+Rename it from sample_fpga_design_config.h to fpga_design_config.h and then
+customize it per your hardware design such as SYS_CLK_FREQ, peripheral
+BASE addresses, interrupt numbers, definition of MSCC_STDIO_UART_BASE_ADDR if
+you want a CoreUARTapb mapped to STDIO, etc.
+
+## Linker script changes
+
+You must make sure that in addition to the reset vector, all other memory address
+configurations in the Mi-V soft processor match with the memory layout defined
+in the linker script.
+
+## Target hardware
+This project is tested on PolarFire Eval Kit MIV_RV32 IMC Core.
+Libero example/job URL here:
+https://mi-v-soft-risc-v.github.io/PolarFire-Eval-Kit/
+
+## Mi-V soft processor revision dependencies
+This project is tested with MIV_RV32 v3.0
diff --git a/miv-rv32-udma/miv-rv32-udma hw attach.launch b/miv-rv32-udma/miv-rv32-udma hw attach.launch
new file mode 100644
index 0000000..e0f8c6c
--- /dev/null
+++ b/miv-rv32-udma/miv-rv32-udma hw attach.launch
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miv-rv32-udma/miv-rv32-udma hw debug.launch b/miv-rv32-udma/miv-rv32-udma hw debug.launch
new file mode 100644
index 0000000..52e8bb3
--- /dev/null
+++ b/miv-rv32-udma/miv-rv32-udma hw debug.launch
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miv-rv32-udma/src/application/main.c b/miv-rv32-udma/src/application/main.c
new file mode 100644
index 0000000..2797825
--- /dev/null
+++ b/miv-rv32-udma/src/application/main.c
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV uDMA Example project
+ *
+ * This project will demonstrate the use of MIV uDMA Bare-metal software driver.
+ * A 32-bit data is written into the source address and the uDMA controller
+ * will copy the data from src_addr to dest_addr.
+ * A verify function will check if the correct data is read or not, and based
+ * on the response, UART messages will be printed.
+ *
+ * Please refer README.md in the root folder of this project for more details.
+ */
+
+#include
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "drivers/fpga_ip/miv_udma/miv_udma.h"
+
+/******************************************************************************
+ * Peripheral instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+miv_udma_instance_t g_miv_ess_udma;
+
+/* Local function to verify the uDMA transaction */
+static uint8_t
+verify_write
+(
+ uint32_t* write_buff,
+ uint32_t* read_buff,
+ uint16_t size
+);
+
+/*
+ * Local Constants to hold the source and destination address
+ * Application developer should update these values as per requirements.
+ */
+#define MIV_UDMA_TRANSFER_SRC_ADDR 0x89000000u
+#define MIV_UDMA_TRANSFER_DEST_ADDR 0x8A000000u
+
+/*==============================================================================
+ * Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\t\t **** PolarFire MiV uDMA Example ****\n\n\n\r\
+This application will demonstrate the use of MIV uDMA bare-metal driver.\r\n\n\
+It will copy the data from MIV_UDMA_TRANSFER_SRC_ADDR to MIV_UDMA_TRANSFER_DEST_ADDR.\r\n\n\
+";
+
+static void display_greeting(void);
+
+uint32_t g_udma_status = 0u;
+
+/*==============================================================================
+ * Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_polled_tx_string(&g_uart, g_greeting_msg);
+}
+
+/* MIV RV32 External interrupt handlers for MIV_ESS uDMA */
+void MSYS_EI1_IRQHandler()
+{
+ g_udma_status = MIV_uDMA_read_status(&g_miv_ess_udma);
+
+ MIV_uDMA_reset(&g_miv_ess_udma);
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+void main(void)
+{
+ size_t rx_size;
+ uint8_t rx_buff[1] = {0x00};
+ uint32_t counter = 0u;
+
+ /* Initialize CoreUARTapb with its base address, baud value, and line
+ * configuration.
+ */
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200, (DATA_8_BITS | NO_PARITY));
+
+ display_greeting();
+
+ MRV_enable_local_irq(MRV32_MSYS_EIE1_IRQn);
+
+ HAL_enable_interrupts();
+
+ uint32_t *src_addr = (uint32_t*)MIV_UDMA_TRANSFER_SRC_ADDR;
+ uint32_t *dest_addr = (uint32_t*)MIV_UDMA_TRANSFER_DEST_ADDR;
+
+ /* Write some data in the source memory */
+ *src_addr = 0xAFAFAFAF;
+
+ MIV_uDMA_init(&g_miv_ess_udma, MIV_ESS_uDMA_BASE_ADDR);
+
+ MIV_uDMA_config(&g_miv_ess_udma, MIV_UDMA_TRANSFER_SRC_ADDR ,
+ MIV_UDMA_TRANSFER_DEST_ADDR, 0x8, MIV_uDMA_CTRL_IRQ_CONFIG);
+
+ MIV_uDMA_start(&g_miv_ess_udma);
+
+ while(1)
+ {
+ if (g_udma_status == MIV_uDMA_STATUS_BUSY)
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\n uDMA busy");
+
+ g_udma_status = 0xff;
+ }
+ else if (g_udma_status == MIV_uDMA_STATUS_ERROR)
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\n uDMA error");
+ g_udma_status = 0xff;
+ }
+ else if (g_udma_status == 0u)
+ {
+ counter = verify_write(src_addr, dest_addr, 8u);
+ if (counter == 0u)
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\n uDMA Success");
+ g_udma_status = 0xff;
+ }
+ else
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\n uDMA wrong data");
+ g_udma_status = 0xff;
+ }
+ }
+ }
+}
+
+/**************************************************************************//**
+ * Read the data from destination memory and compare the same with source
+ * address contents.
+ */
+static uint8_t verify_write(uint32_t* write_buff, uint32_t* read_buff, uint16_t size)
+{
+ uint8_t error = 0U;
+ uint16_t index = 0U;
+
+ while(size != 0U)
+ {
+ if(write_buff[index] != read_buff[index])
+ {
+ error = 1U;
+ break;
+ }
+ index++;
+ size--;
+ }
+
+ return error;
+}
diff --git a/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design/design_description/README.md b/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design/design_description/README.md
new file mode 100644
index 0000000..4f7aa4b
--- /dev/null
+++ b/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design/design_description/README.md
@@ -0,0 +1,2 @@
+# Desgin desctription
+The Libero generated design desctription will be stored here.
diff --git a/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..524ef50
--- /dev/null
+++ b/miv-rv32-udma/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright 2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file sample_fpga_design_config.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Sample design configuration settings
+ *
+ */
+ /*========================================================================*//**
+ @mainpage
+ Example file detailing how the fpga_design_config.h should be constructed
+ for the SoftConsole project targeted for Mi-V processors.
+
+ @section intro_sec Introduction
+ The SoftConsole project targeted for Mi-V processors now have an improved
+ folder structure. Detailed description of the folder structure is available
+ at https://github.com/Mi-V-Soft-RISC-V/miv-rv32-documentation.
+
+ The fpga_design_config.h must be stored as shown below
+ /boards//fpga_design_config.h
+
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.
+ In future, all the design and soft IP configurations will be automatically
+ generated from the Libero design description data.
+
+ You can use this sample file as an example.
+ Rename this file from sample_fpga_design_config.h to fpga_design_config.h
+ and then customize it per your hardware design.
+
+ @section driver_configuration Project configuration Instructions
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock
+ 2 Add all the soft IP core BASE addresses
+ 3. Add the peripheral Core Interrupts to Mi-V Soft processor IRQ number
+ mappings
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to
+ STDIO
+
+ **NOTE**
+ In the legacy folder structures, the file hw_config.h as was used at the
+ root of the project folder. This file is now deprecated.
+
+*//*=========================================================================*/
+
+#ifndef FPGA_DESIGN_CONFIG_H_
+#define FPGA_DESIGN_CONFIG_H_
+
+/***************************************************************************//**
+ * Soft-processor clock definition
+ * This is the only clock brought over from the Mi-V Soft processor Libero design.
+ */
+#define SYS_CLK_FREQ 50000000UL
+
+/***************************************************************************//**
+ * Non-memory Peripheral base addresses
+ * Format of define is:
+ * __BASE_ADDR
+ */
+#define MIV_ESS_BASE_ADDR 0x70000000UL
+#define COREUARTAPB0_BASE_ADDR 0x71000000UL
+#define COREGPIO_BASE_ADDR 0x75000000UL
+#define MIV_ESS_uDMA_BASE_ADDR 0x78000000UL
+
+
+/***************************************************************************//**
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor
+ * interrupt from the Libero design.
+ *
+ * On the legacy RV32 cores, there can be up to 31 external interrupts (IRQ[30:0]
+ * pins). The legacy RV32 Soft processor external interrupts are defined in the
+ riscv_plic.h
+ *
+ * These are of the form
+ * typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ .
+ .
+ .
+ External_31_IRQn = 31
+} IRQn_Type;
+
+ On the legacy RV32 processors, the PLIC identifies the interrupt and passes it
+ on to the processor core. The interrupt 0 is not used. The pin IRQ[0] should
+ map to External_1_IRQn likewise IRQ[30] should map to External_31_IRQn
+
+e.g
+
+#define TIMER0_IRQn External_30_IRQn
+#define TIMER1_IRQn External_31_IRQn
+
+ The MIV_RV32 have up to six optional system interrupts, MSYS_EI[n] in addition
+ to one EXT_IRQ.
+ On the MIV_RV32 does not have an inbuilt PLIC and all the interrupts are directly
+ delivered to the processor core, hence unlike legacy RV32 core no interrupt
+ number mapping is necessary on MIV_RV32 core.
+ */
+
+/****************************************************************************
+ * Baud value to achieve a 115200 baud rate with system clock defined by
+ * SYS_CLK_FREQ.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+#define BAUD_VALUE_115200 ((SYS_CLK_FREQ / (16 * 115200)) - 1)
+
+/******************************************************************************
+ * Baud value to achieve a 57600 baud rate with system clock defined by
+ * SYS_CLK_FREQ.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ #define BAUD_VALUE_57600 ((SYS_CLK_FREQ / (16 * 57600)) - 1)
+
+/***************************************************************************//**
+ * Define MSCC_STDIO_THRU_CORE_UART_APB in the project settings if you want the
+ * standard IOs to be redirected to a terminal via UART.
+ */
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+/*
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb
+ * must be provided if it is being used
+ *
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+ */
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR
+
+#ifndef MSCC_STDIO_UART_BASE_ADDR
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+#endif
+
+#ifndef MSCC_STDIO_BAUD_VALUE
+/*
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to
+ * specify the baud value used by the standard output CoreUARTapb instance for
+ * generating the UART's baud rate if you want a different baud rate from the
+ * default of 115200 baud
+ */
+#define MSCC_STDIO_BAUD_VALUE 115200
+#endif /*MSCC_STDIO_BAUD_VALUE*/
+
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */
+/*******************************************************************************
+ * End of user edit section
+ */
+#endif /* FPGA_DESIGN_CONFIG_H_ */
+
+
diff --git a/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-execute-in-place.ld b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..19df5fb
--- /dev/null
+++ b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-execute-in-place.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * image executing from a one address space whereas the data, sdata and stack
+ * sections are placed in another address space. This could be used in cases such
+ * as:
+ * 1) When using MIV_RV32, the reset vector points to the LSRAM at address
+ * 0x80000000 and the data, sdata, bss and stack sections are placed in the
+ * TCM region.
+ *
+ * 2) Executing from a Non Volatile memory. The actual memory will depend on
+ * the FPGA platform. For exameple, it could be the eNVM on SmartFusion2,
+ * Igloo2 or on-board non-volatile memory which supports code execution.
+ *
+ * NOTE: Modify the memory section addresses and the sizes according to your
+ * Libero design.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x80000000, LENGTH = 16k
+ ram (rwx) : ORIGIN = 0x80004000, LENGTH = 16k
+}
+
+STACK_SIZE = 1k; /* needs to be calculated for your application */
+HEAP_SIZE = 0; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > rom
+
+ .text : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.text.entry)))
+ . = ALIGN(0x10);
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } >rom
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } >ram AT>rom
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } >ram AT>rom
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..e0707df
--- /dev/null
+++ b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-ram.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * debug image executing in SRAM.
+ *
+ * This linker script assumes that a RAM is connected at on Mi-V soft processor
+ * memory space pointed by the reset vector address.
+ *
+ * NOTE : Modify the memory section address and the size according to your
+ * Libero design.
+ * For example:
+ * 1) If you want to download and step debug at a different RAM memory address in
+ * your design (For example TCM base address) than the one provided in this file.
+ * 2) The MIV_RV32, when used with MIV_ESS IP, provides ways to copy the executable
+ * HEX file from external Non-Volatile memory into the TCM at reset. In this
+ * case your executable must be linked to the TCM address.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 32k
+}
+
+STACK_SIZE = 2k; /* needs to be calculated for your application */
+HEAP_SIZE = 0k; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > ram
+
+ .text : ALIGN(0x10)
+ {
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } > ram
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } > ram
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } > ram
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/miv_rv32_hal_config/readme.md b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/miv_rv32_hal_config/readme.md
new file mode 100644
index 0000000..46ee0bd
--- /dev/null
+++ b/miv-rv32-udma/src/boards/polarfire-eval-kit/platform_config/miv_rv32_hal_config/readme.md
@@ -0,0 +1,2 @@
+# readme
+Software configurations that may be required for MIV_RV32 HAL in future will be stored here.
diff --git a/miv-rv32-udma/src/middleware/README.md b/miv-rv32-udma/src/middleware/README.md
new file mode 100644
index 0000000..dafa1d2
--- /dev/null
+++ b/miv-rv32-udma/src/middleware/README.md
@@ -0,0 +1 @@
+Place holder readme file in the middleware directory.
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..63cd377
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,531 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * @file core_gpio.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreGPIO bare metal driver implementation.
+ *
+ */
+#include "coregpio_regs.h"
+#include "core_gpio.h"
+
+/*-------------------------------------------------------------------------*//**
+ *
+ */
+#define GPIO_INT_ENABLE_MASK (uint32_t)0x00000008UL
+#define OUTPUT_BUFFER_ENABLE_MASK 0x00000004UL
+
+
+#define NB_OF_GPIO 32
+
+#define CLEAR_ALL_IRQ32 (uint32_t)0xFFFFFFFF
+#define CLEAR_ALL_IRQ16 (uint16_t)0xFFFF
+#define CLEAR_ALL_IRQ8 (uint8_t)0xFF
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_init()
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_init
+(
+ gpio_instance_t * this_gpio,
+ addr_t base_addr,
+ gpio_apb_width_t bus_width
+)
+{
+ uint8_t i = 0;
+ addr_t cfg_reg_addr = base_addr;
+
+ this_gpio->base_addr = base_addr;
+ this_gpio->apb_bus_width = bus_width;
+
+ /* Clear configuration. */
+ for( i = 0, cfg_reg_addr = base_addr; i < NB_OF_GPIO; ++i )
+ {
+ HW_set_8bit_reg( cfg_reg_addr, 0 );
+ cfg_reg_addr += 4;
+ }
+ /* Clear any pending interrupts */
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, CLEAR_ALL_IRQ32 );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, (uint16_t)CLEAR_ALL_IRQ16 );
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, (uint16_t)CLEAR_ALL_IRQ16 );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, (uint8_t)CLEAR_ALL_IRQ8 );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_config
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_config
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint32_t config
+)
+{
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+ cfg_reg_addr += (port_id * 4);
+ HW_set_32bit_reg( cfg_reg_addr, config );
+
+ /*
+ * Verify that the configuration was correctly written. Failure to read
+ * back the expected value may indicate that the GPIO port was configured
+ * as part of the hardware flow and cannot be modified through software.
+ * It may also indicate that the base address passed as parameter to
+ * GPIO_init() was incorrect.
+ */
+ HAL_ASSERT( HW_get_32bit_reg( cfg_reg_addr ) == config );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_set_outputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_set_outputs
+(
+ gpio_instance_t * this_gpio,
+ uint32_t value
+)
+{
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, value );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint16_t)value );
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint16_t)(value >> 16) );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint8_t)value );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint8_t)(value >> 8) );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT2, (uint8_t)(value >> 16) );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT3, (uint8_t)(value >> 24) );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( GPIO_get_outputs( this_gpio ) == value );
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_get_inputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+uint32_t GPIO_get_inputs
+(
+ gpio_instance_t * this_gpio
+)
+{
+ uint32_t gpio_in = 0;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ gpio_in = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_IN );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ gpio_in |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN0 );
+ gpio_in |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 16);
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ gpio_in |= HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN0 );
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 8);
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN2 ) << 16);
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN3 ) << 24);
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ return gpio_in;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_get_outputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+uint32_t GPIO_get_outputs
+(
+ gpio_instance_t * this_gpio
+)
+{
+ uint32_t gpio_out = 0;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ gpio_out = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 16);
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 8);
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT2 ) << 16);
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT3 ) << 24);
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ return gpio_out;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_set_output
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_set_output
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint8_t value
+)
+{
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ {
+ uint32_t outputs_state;
+
+ outputs_state = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << port_id);
+ }
+ else
+ {
+ outputs_state |= 1 << port_id;
+ }
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT ) == outputs_state );
+ }
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ {
+ uint16_t outputs_state;
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 4) * 4);
+
+ outputs_state = HW_get_16bit_reg( gpio_out_reg_addr );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << (port_id & 0x0F));
+ }
+ else
+ {
+ outputs_state |= 1 << (port_id & 0x0F);
+ }
+ HW_set_16bit_reg( gpio_out_reg_addr, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HW_get_16bit_reg( gpio_out_reg_addr ) == outputs_state );
+ }
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ {
+ uint8_t outputs_state;
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 3) * 4);
+
+ outputs_state = HW_get_8bit_reg( gpio_out_reg_addr );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << (port_id & 0x07));
+ }
+ else
+ {
+ outputs_state |= 1 << (port_id & 0x07);
+ }
+ HW_set_8bit_reg( gpio_out_reg_addr, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HW_get_8bit_reg( gpio_out_reg_addr ) == outputs_state );
+ }
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_drive_inout
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_drive_inout
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ gpio_inout_state_t inout_state
+)
+{
+ uint32_t config;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ switch( inout_state )
+ {
+ case GPIO_DRIVE_HIGH:
+ /* Set output high */
+ GPIO_set_output( this_gpio, port_id, 1 );
+
+ /* Enable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ case GPIO_DRIVE_LOW:
+ /* Set output low */
+ GPIO_set_output( this_gpio, port_id, 0 );
+
+ /* Enable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ case GPIO_HIGH_Z:
+ /* Disable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config &= ~OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_enable_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_enable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ cfg_reg_addr += (port_id * 4);
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );
+ cfg_value |= GPIO_INT_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_disable_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_disable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ cfg_reg_addr += (port_id * 4);
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );
+ cfg_value &= ~GPIO_INT_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_clear_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_clear_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t irq_clr_value = ((uint32_t)1) << ((uint32_t)port_id);
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, irq_clr_value );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 16 );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, irq_clr_value >> 16 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, irq_clr_value >> 24 );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_get_irq_sources
+ * See "core_gpio.h" for details of how to use this function.
+ */
+uint32_t GPIO_get_irq_sources
+(
+ gpio_instance_t * this_gpio
+)
+{
+ uint32_t intr_src = 0;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ intr_src = HAL_get_32bit_reg( this_gpio->base_addr, IRQ );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ intr_src |= HAL_get_16bit_reg( this_gpio->base_addr, IRQ0 );
+ intr_src |= (HAL_get_16bit_reg( this_gpio->base_addr, IRQ1 ) << 16);
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ intr_src |= HAL_get_16bit_reg( this_gpio->base_addr, IRQ0 );
+ intr_src |= (HAL_get_16bit_reg( this_gpio->base_addr, IRQ1 ) << 8);
+ intr_src |= (HAL_get_16bit_reg( this_gpio->base_addr, IRQ2 ) << 16);
+ intr_src |= (HAL_get_16bit_reg( this_gpio->base_addr, IRQ3 ) << 24);
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ return intr_src;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_clear_all_irq_sources
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_clear_all_irq_sources
+(
+ gpio_instance_t * this_gpio,
+ uint32_t bitmask
+)
+{
+ uint32_t irq_clr_value = bitmask;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, irq_clr_value );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 16 );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, irq_clr_value >> 16 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, irq_clr_value >> 24 );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..3491d68
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,654 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * @file core_gpio.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreGPIO bare metal driver public API.
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage CoreGPIO Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The CoreGPIO hardware IP includes up to 32 general purpose input output GPIOs.
+ This driver provides a set of functions for controlling the GPIOs as part of a
+ bare metal system where no operating system is available. These drivers
+ can be adapted for use as part of an operating system but the implementation
+ of the adaptation layer between this driver and the operating system's driver
+ model is outside the scope of this driver.
+
+ @section driver_configuration Driver Configuration
+ The CoreGPIO individual IOs can be configured either in the hardware flow or
+ as part of the software application through calls to the GPIO_config() function.
+ GPIOs configured as as part of the hardware is fixed and cannot be modified
+ using a call to the GPI_config() function.
+
+ @section theory_op Theory of Operation
+ The CoreGPIO driver uses the Actel Hardware Abstraction Layer (HAL) to access
+ hardware registers. You must ensure that the Actel HAL is included as part of
+ your software project. The Actel HAL is available through the Actel Firmware
+ Catalog.
+
+ The CoreGPIO driver functions are logically grouped into the following groups:
+ - Initialization
+ - Configuration
+ - Reading and writing GPIO state
+ - Interrupt control
+
+ The CoreGPIO driver is initialized through a call to the GPIO_init() function.
+ The GPIO_init() function must be called before any other GPIO driver functions
+ can be called.
+
+ Each GPIO port is individually configured through a call to the
+ GPIO_config() function. Configuration includes deciding if a GPIO port
+ will be used as input, output or both. GPIO ports configured as inputs can be
+ further configured to generate interrupts based on the input's state.
+ Interrupts can be level or edge sensitive.
+ Please note that a CoreGPIO hardware instance can be generated, as part of the
+ hardware flow, with a fixed configuration for some or all of its IOs. Attempting
+ to modify the configuration of such a hardware configured IO using the
+ GPIO_config() function has no effect.
+
+ The state of the GPIO ports can be read and written using the following
+ functions:
+ - GPIO_get_inputs()
+ - GPIO_get_outputs()
+ - GPIO_set_outputs()
+ - GPIO_drive_inout()
+
+ Interrupts generated by GPIO ports configured as inputs are controlled using
+ the following functions:
+ - GPIO_enable_irq()
+ - GPIO_disable_irq()
+ - GPIO_clear_irq()
+ - GPIO_get_irq_sources()
+ - GPIO_clear_all_irq_sources()
+
+ *//*=========================================================================*/
+#ifndef CORE_GPIO_H_
+#define CORE_GPIO_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The gpio_id_t enumeration is used to identify GPIOs as part of the
+ parameter to functions:
+ - GPIO_config(),
+ - GPIO_drive_inout(),
+ - GPIO_enable_int(),
+ - GPIO_disable_int(),
+ - GPIO_clear_int()
+ */
+typedef enum __gpio_id_t
+{
+ GPIO_0 = 0,
+ GPIO_1 = 1,
+ GPIO_2 = 2,
+ GPIO_3 = 3,
+ GPIO_4 = 4,
+ GPIO_5 = 5,
+ GPIO_6 = 6,
+ GPIO_7 = 7,
+ GPIO_8 = 8,
+ GPIO_9 = 9,
+ GPIO_10 = 10,
+ GPIO_11 = 11,
+ GPIO_12 = 12,
+ GPIO_13 = 13,
+ GPIO_14 = 14,
+ GPIO_15 = 15,
+ GPIO_16 = 16,
+ GPIO_17 = 17,
+ GPIO_18 = 18,
+ GPIO_19 = 19,
+ GPIO_20 = 20,
+ GPIO_21 = 21,
+ GPIO_22 = 22,
+ GPIO_23 = 23,
+ GPIO_24 = 24,
+ GPIO_25 = 25,
+ GPIO_26 = 26,
+ GPIO_27 = 27,
+ GPIO_28 = 28,
+ GPIO_29 = 29,
+ GPIO_30 = 30,
+ GPIO_31 = 31
+} gpio_id_t;
+
+typedef enum __gpio_apb_width_t
+{
+ GPIO_APB_8_BITS_BUS = 0,
+ GPIO_APB_16_BITS_BUS = 1,
+ GPIO_APB_32_BITS_BUS = 2,
+ GPIO_APB_UNKNOWN_BUS_WIDTH = 3
+} gpio_apb_width_t;
+
+/*-------------------------------------------------------------------------*//**
+ */
+typedef struct __gpio_instance_t
+{
+ addr_t base_addr;
+ gpio_apb_width_t apb_bus_width;
+} gpio_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ GPIO ports definitions used to identify GPIOs as part of the parameter to
+ function GPIO_set_outputs().
+ These definitions can also be used to identity GPIO through logical
+ operations on the return value of function GPIO_get_inputs().
+ */
+#define GPIO_0_MASK 0x00000001UL
+#define GPIO_1_MASK 0x00000002UL
+#define GPIO_2_MASK 0x00000004UL
+#define GPIO_3_MASK 0x00000008UL
+#define GPIO_4_MASK 0x00000010UL
+#define GPIO_5_MASK 0x00000020UL
+#define GPIO_6_MASK 0x00000040UL
+#define GPIO_7_MASK 0x00000080UL
+#define GPIO_8_MASK 0x00000100UL
+#define GPIO_9_MASK 0x00000200UL
+#define GPIO_10_MASK 0x00000400UL
+#define GPIO_11_MASK 0x00000800UL
+#define GPIO_12_MASK 0x00001000UL
+#define GPIO_13_MASK 0x00002000UL
+#define GPIO_14_MASK 0x00004000UL
+#define GPIO_15_MASK 0x00008000UL
+#define GPIO_16_MASK 0x00010000UL
+#define GPIO_17_MASK 0x00020000UL
+#define GPIO_18_MASK 0x00040000UL
+#define GPIO_19_MASK 0x00080000UL
+#define GPIO_20_MASK 0x00100000UL
+#define GPIO_21_MASK 0x00200000UL
+#define GPIO_22_MASK 0x00400000UL
+#define GPIO_23_MASK 0x00800000UL
+#define GPIO_24_MASK 0x01000000UL
+#define GPIO_25_MASK 0x02000000UL
+#define GPIO_26_MASK 0x04000000UL
+#define GPIO_27_MASK 0x08000000UL
+#define GPIO_28_MASK 0x10000000UL
+#define GPIO_29_MASK 0x20000000UL
+#define GPIO_30_MASK 0x40000000UL
+#define GPIO_31_MASK 0x80000000UL
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO modes
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ */
+#define GPIO_IRQ_LEVEL_HIGH 0x0000000000UL
+#define GPIO_IRQ_LEVEL_LOW 0x0000000020UL
+#define GPIO_IRQ_EDGE_POSITIVE 0x0000000040UL
+#define GPIO_IRQ_EDGE_NEGATIVE 0x0000000060UL
+#define GPIO_IRQ_EDGE_BOTH 0x0000000080UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible states for GPIO configured as INOUT.
+ */
+typedef enum gpio_inout_state
+{
+ GPIO_DRIVE_LOW = 0,
+ GPIO_DRIVE_HIGH,
+ GPIO_HIGH_Z
+} gpio_inout_state_t;
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_init() function initialises a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Please note that a CoreGPIO hardware instance can be generated with a fixed
+ configuration for some or all of its IOs as part of the hardware flow. Attempting
+ to modify the configuration of such a hardware configured IO using the
+ GPIO_config() function has no effect.
+
+ @param this_gpio
+ Pointer to the gpio_instance_t data structure instance holding all data
+ regarding the CoreGPIO hardware instance being initialized. A pointer to the
+ same data structure will be used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that should perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the GPIO instance being initialized.
+
+ @param bus_width
+ The bus_width parameter informs the driver of the APB bus width selected during
+ the hardware flow configuration of the CoreGPIO hardware instance. It indicates
+ to the driver whether the CoreGPIO hardware registers will be visible as 8, 16
+ or 32 bits registers. Allowed value are:
+ - GPIO_APB_8_BITS_BUS
+ - GPIO_APB_16_BITS_BUS
+ - GPIO_APB_32_BITS_BUS
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREGPIO_BASE_ADDR 0xC2000000
+
+ gpio_instance_t g_gpio;
+
+ void system_init( void )
+ {
+ GPIO_init( &g_gpio, COREGPIO_BASE_ADDR, GPIO_APB_32_BITS_BUS );
+ }
+ @endcode
+ */
+void GPIO_init
+(
+ gpio_instance_t * this_gpio,
+ addr_t base_addr,
+ gpio_apb_width_t bus_width
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_config() function is used to configure an individual GPIO port.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port to be configured.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @param config
+ The config parameter specifies the configuration to be applied to the GPIO
+ port identified by the first parameter. It is a logical OR of GPIO mode and
+ the interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as input.
+ Possible modes are:
+ - GPIO_INPUT_MODE,
+ - GPIO_OUTPUT_MODE,
+ - GPIO_INOUT_MODE.
+ Possible interrupt modes are:
+ - GPIO_IRQ_LEVEL_HIGH,
+ - GPIO_IRQ_LEVEL_LOW,
+ - GPIO_IRQ_EDGE_POSITIVE,
+ - GPIO_IRQ_EDGE_NEGATIVE,
+ - GPIO_IRQ_EDGE_BOTH
+
+ @return
+ none.
+
+ For example the following call will configure GPIO 4 as an input generating
+ interrupts on a low to high transition of the input:
+ @code
+ GPIO_config( &g_gpio, GPIO_4, GPIO_INPUT_MODE | GPIO_IRQ_EDGE_POSITIVE );
+ @endcode
+ */
+void GPIO_config
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint32_t config
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_set_outputs() function is used to set the state of the GPIO ports
+ configured as outputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param value
+ The value parameter specifies the state of the GPIO ports configured as
+ outputs. It is a bit mask of the form (GPIO_n_MASK | GPIO_m_MASK) where n
+ and m are numbers identifying GPIOs.
+ For example (GPIO_0_MASK | GPIO_1_MASK | GPIO_2_MASK ) specifies that the
+ first, second and third GPIOs' must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ Example 1:
+ Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ Example 2:
+ Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.
+ @code
+ uint32_t gpio_outputs;
+ gpio_outputs = GPIO_get_outputs( &g_gpio );
+ gpio_outputs &= ~( GPIO_2_MASK | GPIO_4_MASK );
+ GPIO_set_outputs( &g_gpio, gpio_outputs );
+ @endcode
+
+ @see GPIO_get_outputs()
+ */
+void GPIO_set_outputs
+(
+ gpio_instance_t * this_gpio,
+ uint32_t value
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_set_output() function is used to set the state of a single GPIO
+ port configured as output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that will have its output set
+ by a call to this function.
+
+ @param value
+ The value parameter specifies the desired state for the GPIO output. A value
+ of 0 will set the output low and a value of 1 will set the port high.
+
+ @return
+ none.
+ */
+void GPIO_set_output
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint8_t value
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_get_inputs() function is used to read the state of all GPIOs
+ configured as inputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @return
+ This function returns a 32 bit unsigned integer where each bit represents
+ the state of an input. The least significant bit representing the state of
+ GPIO 0 and the most significant bit the state of GPIO 31.
+ */
+uint32_t GPIO_get_inputs
+(
+ gpio_instance_t * this_gpio
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_get_outputs() function is used to read the current state of all
+ GPIO outputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @return
+ This function returns a 32 bit unsigned integer where each bit represents
+ the state of an output. The least significant bit representing the state
+ of GPIO 0 and the most significant bit the state of GPIO 31.
+ */
+uint32_t GPIO_get_outputs
+(
+ gpio_instance_t * this_gpio
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_drive_inout() function is used to set the output state of a
+ GPIO configured as INOUT. An INOUT GPIO can be in one of three states:
+ - high
+ - low
+ - high impedance
+ An INOUT output would typically be used where several devices can drive the
+ state of a signal. The high and low states are equivalent to the high and low
+ states of a GPIO configured as output. The high impedance state is used to
+ prevent the GPIO from driving the state of the output and therefore allow
+ reading the state of the GPIO as an input.
+ Please note that the GPIO port you wish to use as INOUT through this function
+ must be configurable through software. Therefore the GPIO ports used as INOUT
+ must not have a fixed configuration selected as part of the hardware flow.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO for which this function will
+ change the output state.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @param inout_state
+ The inout_state parameter specifies the state of the I/O identified by the
+ first parameter. Possible states are:
+ - GPIO_DRIVE_HIGH,
+ - GPIO_DRIVE_LOW,
+ - GPIO_HIGH_Z (high impedance)
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_drive_inout() below will set the GPIO 7 output to
+ high impedance state.
+ @code
+ GPIO_drive_inout( &g_gpio, GPIO_7, GPIO_HIGH_Z );
+ @endcode
+ */
+void GPIO_drive_inout
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ gpio_inout_state_t inout_state
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_enable_irq() function is used to enable an interrupt to be
+ generated based on the state of the input identified as parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input the call to
+ GPIO_enable_irq() will enable to generate interrupts.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_enable_irq() below will allow GPIO 8 to generate
+ interrupts.
+ @code
+ GPIO_enable_irq( &g_gpio, GPIO_8 );
+ @endcode
+ */
+void GPIO_enable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_disable_irq() function is used to disable interrupt from being
+ generated based on the state of the input specified as parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input the call to
+ GPIO_disable_irq() will disable from generating interrupts.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_disable_irq() below will prevent GPIO 8 from generating
+ interrupts.
+ @code
+ GPIO_disable_irq( &g_gpio, GPIO_8 );
+ @endcode
+ */
+void GPIO_disable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_clear_irq() function is used to clear the interrupt generated by
+ the GPIO specified as parameter. The GPIO_clear_irq() function must be
+ called as part of a GPIO interrupt service routine (ISR) in order to prevent
+ the same interrupt event re-triggering a call to the GPIO ISR.
+ Please note that interrupts may also need to be cleared in the processor's
+ interrupt controller.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input for which to clear the
+ interrupt.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The example below demonstrates the use of the GPIO_clear_irq() function as
+ part of the GPIO 9 interrupt service routine.
+ @code
+ void GPIO9_IRQHandler( void )
+ {
+ do_interrupt_processing();
+
+ GPIO_clear_irq( &g_gpio, GPIO_9 );
+
+ NVIC_ClearPendingIRQ( GPIO9_IRQn );
+ }
+ @endcode
+ */
+void GPIO_clear_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_get_irq_sources() function is used to identify the source of
+ interrupt. i.e. the GPIO input line whose state change triggered the interrupt.
+ The GPIO_get_irq_sources() function must be called as part of a GPIO
+ interrupt service routine (ISR) in order to determine the interrupt source.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @return
+ This function returns a 32 bit unsigned integer where each bit represents
+ the pin number of GPIO.
+
+ Example:
+ The example below demonstrates the use of the GPIO_get_irq_sources() function
+ as part of the GPIO 9 interrupt service routine.
+ @code
+ void GPIO9_IRQHandler( void )
+ {
+ do_interrupt_processing();
+
+ GPIO_clear_all_irq_sources(g_p_mygpio, GPIO_get_irq_sources(g_p_mygpio));
+
+ NVIC_ClearPendingIRQ( GPIO9_IRQn );
+ }
+ @endcode
+ */
+uint32_t GPIO_get_irq_sources
+(
+ gpio_instance_t * this_gpio
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_clear_all_irq_sources() function is used to clear the all the active
+ interrupt generated by the GPIO specified as parameter. The
+ GPIO_clear_all_irq_sources() function must be called as part of a GPIO interrupt
+ service routine (ISR) in order to prevent the same interrupt event
+ re-triggering a call to the GPIO ISR.
+ Please note that interrupts may also need to be cleared in the processor's
+ interrupt controller.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param bitmask
+ This bitmask parameter is a 32 bit unsigned integer where each bit represents
+ the GPIO pin used to clears the interrupt bit register of the corresponding
+ GPIO bit. The least significant bit representing the status of GPIO 0 and
+ the most significant bit the status of GPIO 31.
+
+ @return
+ none.
+
+ Example:
+ The example below demonstrates the use of the GPIO_clear_all_irq_sources() function as
+ part of the GPIO 9 interrupt service routine.
+ @code
+ void GPIO9_IRQHandler( void )
+ {
+ do_interrupt_processing();
+
+ do_interrupt_processing();
+
+ GPIO_clear_all_irq_sources(g_p_mygpio, GPIO_get_irq_sources(g_p_mygpio));
+
+ NVIC_ClearPendingIRQ( GPIO9_IRQn );
+ }
+ @endcode
+ */
+void GPIO_clear_all_irq_sources
+(
+ gpio_instance_t * this_gpio,
+ uint32_t bitmask
+);
+#endif /* CORE_GPIO_H_ */
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..0c13e28
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * @file coregpio_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreGPIO register definitions
+ *
+ */
+
+#ifndef __CORE_GPIO_REGISTERS_H
+#define __CORE_GPIO_REGISTERS_H 1
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define IRQ_REG_OFFSET 0x80
+
+#define IRQ0_REG_OFFSET 0x80
+#define IRQ1_REG_OFFSET 0x84
+#define IRQ2_REG_OFFSET 0x88
+#define IRQ3_REG_OFFSET 0x8C
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define GPIO_IN_REG_OFFSET 0x90
+
+#define GPIO_IN0_REG_OFFSET 0x90
+#define GPIO_IN1_REG_OFFSET 0x94
+#define GPIO_IN2_REG_OFFSET 0x98
+#define GPIO_IN3_REG_OFFSET 0x9C
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define GPIO_OUT_REG_OFFSET 0xA0
+
+#define GPIO_OUT0_REG_OFFSET 0xA0
+#define GPIO_OUT1_REG_OFFSET 0xA4
+#define GPIO_OUT2_REG_OFFSET 0xA8
+#define GPIO_OUT3_REG_OFFSET 0xAC
+
+#endif /* __CORE_GPIO_REGISTERS_H */
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..2b2087a
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * @file core_uart_apb.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreUARTapb driver implementation. See file "core_uart_apb.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "coreuartapb_regs.h"
+#include "core_uart_apb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_INSTANCE ( ( UART_instance_t* ) 0 )
+#define NULL_BUFFER ( ( uint8_t* ) 0 )
+
+#define MAX_LINE_CONFIG ( ( uint8_t )( DATA_8_BITS | ODD_PARITY ) )
+#define MAX_BAUD_VALUE ( ( uint16_t )( 0x1FFF ) )
+#define STATUS_ERROR_MASK ( ( uint8_t )( STATUS_PARITYERR_MASK | \
+ STATUS_OVERFLOW_MASK | \
+ STATUS_FRAMERR_MASK ) )
+#define BAUDVALUE_LSB ( (uint16_t) (0x00FF) )
+#define BAUDVALUE_MSB ( (uint16_t) (0xFF00) )
+#define BAUDVALUE_SHIFT ( (uint8_t) (5) )
+
+#define STATUS_ERROR_OFFSET STATUS_PARITYERR_SHIFT
+
+/***************************************************************************//**
+ * UART_init()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_init
+(
+ UART_instance_t * this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+)
+{
+ uint8_t rx_full;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( line_config <= MAX_LINE_CONFIG )
+ HAL_ASSERT( baud_value <= MAX_BAUD_VALUE )
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( line_config <= MAX_LINE_CONFIG ) &&
+ ( baud_value <= MAX_BAUD_VALUE ) )
+ {
+ /*
+ * Store lower 8-bits of baud value in CTRL1.
+ */
+ HAL_set_8bit_reg( base_addr, CTRL1, (uint_fast8_t)(baud_value &
+ BAUDVALUE_LSB ) );
+
+ /*
+ * Extract higher 5-bits of baud value and store in higher 5-bits
+ * of CTRL2, along with line configuration in lower 3 three bits.
+ */
+ HAL_set_8bit_reg( base_addr, CTRL2, (uint_fast8_t)line_config |
+ (uint_fast8_t)((baud_value &
+ BAUDVALUE_MSB) >> BAUDVALUE_SHIFT ) );
+
+ this_uart->base_address = base_addr;
+#ifndef NDEBUG
+ {
+ uint8_t config;
+ uint8_t temp;
+ uint16_t baud_val;
+ baud_val = HAL_get_8bit_reg( this_uart->base_address, CTRL1 );
+ config = HAL_get_8bit_reg( this_uart->base_address, CTRL2 );
+ /*
+ * To resolve operator precedence between & and <<
+ */
+ temp = ( config & (uint8_t)(CTRL2_BAUDVALUE_MASK ) );
+ baud_val |= (uint16_t)( (uint16_t)(temp) << BAUDVALUE_SHIFT );
+ config &= (uint8_t)(~CTRL2_BAUDVALUE_MASK);
+ HAL_ASSERT( baud_val == baud_value );
+ HAL_ASSERT( config == line_config );
+ }
+#endif
+
+ /*
+ * Flush the receive FIFO of data that may have been received before the
+ * driver was initialized.
+ */
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_RXFULL_MASK;
+ while ( rx_full )
+ {
+ HAL_get_8bit_reg( this_uart->base_address, RXDATA );
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_RXFULL_MASK;
+ }
+
+ /*
+ * Clear status of the UART instance.
+ */
+ this_uart->status = (uint8_t)0;
+ }
+}
+
+/***************************************************************************//**
+ * UART_send()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_send
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ size_t char_idx;
+ uint8_t tx_ready;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )
+ HAL_ASSERT( tx_size > 0 )
+
+ if( (this_uart != NULL_INSTANCE) &&
+ (tx_buffer != NULL_BUFFER) &&
+ (tx_size > (size_t)0) )
+ {
+ for ( char_idx = (size_t)0; char_idx < tx_size; char_idx++ )
+ {
+ /* Wait for UART to become ready to transmit. */
+ do {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( !tx_ready );
+ /* Send next character in the buffer. */
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)tx_buffer[char_idx] );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_fill_tx_fifo()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+size_t
+UART_fill_tx_fifo
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ uint8_t tx_ready;
+ size_t size_sent = 0u;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )
+ HAL_ASSERT( tx_size > 0 )
+
+ /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
+ * buffer has been written. */
+ if( (this_uart != NULL_INSTANCE) &&
+ (tx_buffer != NULL_BUFFER) &&
+ (tx_size > 0u) )
+ {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ if ( tx_ready )
+ {
+ do {
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)tx_buffer[size_sent] );
+ size_sent++;
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( (tx_ready) && ( size_sent < tx_size ) );
+ }
+ }
+ return size_sent;
+}
+
+/***************************************************************************//**
+ * UART_get_rx()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+size_t
+UART_get_rx
+(
+ UART_instance_t * this_uart,
+ uint8_t * rx_buffer,
+ size_t buff_size
+)
+{
+ uint8_t new_status;
+ uint8_t rx_full;
+ size_t rx_idx = 0u;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( rx_buffer != NULL_BUFFER )
+ HAL_ASSERT( buff_size > 0 )
+
+ if( (this_uart != NULL_INSTANCE) &&
+ (rx_buffer != NULL_BUFFER) &&
+ (buff_size > 0u) )
+ {
+ rx_idx = 0u;
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
+ this_uart->status |= new_status;
+ rx_full = new_status & STATUS_RXFULL_MASK;
+ while ( ( rx_full ) && ( rx_idx < buff_size ) )
+ {
+ rx_buffer[rx_idx] = HAL_get_8bit_reg( this_uart->base_address,
+ RXDATA );
+ rx_idx++;
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
+ this_uart->status |= new_status;
+ rx_full = new_status & STATUS_RXFULL_MASK;
+ }
+ }
+ return rx_idx;
+}
+
+/***************************************************************************//**
+ * UART_polled_tx_string()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_polled_tx_string
+(
+ UART_instance_t * this_uart,
+ const uint8_t * p_sz_string
+)
+{
+ uint32_t char_idx;
+ uint8_t tx_ready;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( p_sz_string != NULL_BUFFER )
+
+ if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFFER ) )
+ {
+ char_idx = 0U;
+ while( 0U != p_sz_string[char_idx] )
+ {
+ /* Wait for UART to become ready to transmit. */
+ do {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( !tx_ready );
+ /* Send next character in the buffer. */
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)p_sz_string[char_idx] );
+ char_idx++;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_get_rx_status()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+uint8_t
+UART_get_rx_status
+(
+ UART_instance_t * this_uart
+)
+{
+ uint8_t status = UART_APB_INVALID_PARAM;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ /*
+ * Extract UART error status and place in lower bits of "status".
+ * Bit 0 - Parity error status
+ * Bit 1 - Overflow error status
+ * Bit 2 - Frame error status
+ */
+ if( this_uart != NULL_INSTANCE )
+ {
+ status = ( ( this_uart->status & STATUS_ERROR_MASK ) >>
+ STATUS_ERROR_OFFSET );
+ /*
+ * Clear the sticky status for this instance.
+ */
+ this_uart->status = (uint8_t)0;
+ }
+ return status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..2ce0b88
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * @file core_uart_apb.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This file contains the application programming interface for the
+ * CoreUARTapb bare metal driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreUARTapb Bare Metal Driver.
+
+ @section intro_sec Introduction
+ CoreUARTapb is an implementation of the Universal Asynchronous
+ Receiver/Transmitter aimed at a minimal FPGA tile usage within an Microsemi
+ FPGA. The CoreUARTapb bare metal software driver is designed for use in
+ systems with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provides functions allowing use of the
+ CoreUARTapb in interrupt-driven mode, but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling cannot be
+ controlled through the CoreUARTapb registers. The CoreUARTapb driver is
+ provided as C source code.
+
+ @section driver_configuration Driver Configuration
+ Your application software should configure the CoreUARTapb driver, through
+ calls to the UART_init() function for each CoreUARTapb instance in the
+ hardware design. The configuration parameters include the CoreUARTapb
+ hardware instance base address and other runtime parameters, such as baud
+ rate, bit width, and parity. No CoreUARTapb hardware configuration parameters
+ are needed by the driver, apart from the CoreUARTapb hardware instance base
+ address. Hence, no additional configuration files are required to use the driver.
+
+ A CoreUARTapb hardware instance can be generated with fixed baud value,
+ character size and parity configuration settings as part of the hardware flow.
+ The baud_value and line_config parameter values passed to the UART_init()
+ function will not have any effect if fixed values were selected for the
+ baud value, character size and parity in the hardware configuration of
+ CoreUARTapb. When fixed values are selected for these hardware configuration
+ parameters, the driver cannot overwrite the fixed values in the CoreUARTapb
+ control registers, CTRL1 and CTRL2.
+
+ @section theory_op Theory of Operation
+ The CoreUARTapb software driver is designed to allow the control of multiple
+ instances of CoreUARTapb. Each instance of CoreUARTapb in the hardware design
+ is associated with a single instance of the UART_instance_t structure in the
+ software. You need to allocate memory for one unique UART_instance_t
+ structure instance for each CoreUARTapb hardware instance. The contents of
+ these data structures are initialized during calls to function UART_init().
+ A pointer to the structure is passed to subsequent driver functions in order
+ to identify the CoreUARTapb hardware instance you wish to perform the
+ requested operation on.
+
+ Note: Do not attempt to directly manipulate the content of UART_instance_t
+ structures. This structure is only intended to be modified by the driver
+ function.
+
+ The driver can be used to transmit and receive data once initialized.
+ Transmit can be performed using the UART_send() function. This function
+ is blocking, meaning that it will only return once the data passed to
+ the function has been sent to the CoreUARTapb hardware. Data received
+ by the CoreUARTapb hardware can be read by the user application using
+ the UART_get_rx() function.
+
+ The function UART_fill_tx_fifo() is also provided to be used as part of
+ interrupt-driven transmit. This function fills the CoreUARTapb hardware
+ transmit FIFO with the content of a data buffer passed as a parameter before
+ returning. The control of the interrupts must be implemented outside the
+ driver as the CoreUARTapb hardware does not provide the ability to enable
+ or disable its interrupt sources.
+
+ The function UART_polled_tx_string() is provided to transmit a NULL
+ terminated string in polled mode. This function is blocking, meaning that it
+ will only return once the data passed to the function has been sent to the
+ CoreUARTapb hardware.
+
+ The function UART_get_rx_status() returns the error status of the CoreUARTapb
+ receiver. This can be used by applications to take appropriate action in case
+ of receiver errors.
+*//*=========================================================================*/
+#ifndef __CORE_UART_APB_H
+#define __CORE_UART_APB_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * Data bits length defines:
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ * Parity defines:
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ * Error Status definitions:
+ */
+#define UART_APB_PARITY_ERROR 0x01u
+#define UART_APB_OVERFLOW_ERROR 0x02u
+#define UART_APB_FRAMING_ERROR 0x04u
+#define UART_APB_NO_ERROR 0x00u
+#define UART_APB_INVALID_PARAM 0xFFu
+
+/***************************************************************************//**
+ * UART_instance_t
+ *
+ * There should be one instance of this structure for each instance of CoreUARTapb
+ * in your system. This structure instance is used to identify the various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART should perform the requested operation. The 'status'
+ * element in the structure is used to provide sticky status information.
+ */
+typedef struct
+{
+ addr_t base_address;
+ uint8_t status;
+} UART_instance_t;
+
+/***************************************************************************//**
+ * The function UART_init() initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value used to
+ * generate the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the CoreUARTapb. This pointer will be used to identify
+ * the target CoreUARTapb hardware instance in subsequent
+ * calls to the CoreUARTapb functions.
+ * @param base_addr The base_address parameter is the base address in the
+ * processor's memory map for the registers of the
+ * CoreUARTapb instance being initialized.
+ * @param baud_value The baud_value parameter is used to select the baud rate
+ * for the UART. The baud value is calculated from the
+ * frequency of the system clock in hertz and the desired
+ * baud rate using the following equation:
+ *
+ * baud_value = (clock /(baud_rate * 16)) - 1.
+ *
+ * The baud_value parameter must be a value in the range 0
+ * to 8191 (or 0x0000 to 0x1FFF).
+ * @param line_config This parameter is the line configuration specifying the
+ * bit length and parity settings. This is a logical OR of:
+ * - DATA_7_BITS
+ * - DATA_8_BITS
+ * - NO_PARITY
+ * - EVEN_PARITY
+ * - ODD_PARITY
+ * For example, 8 bits even parity would be specified as
+ * (DATA_8_BITS | EVEN_PARITY).
+ * @return This function does not return a value.
+ * Example:
+ * @code
+ * #define BAUD_VALUE_57600 25
+ *
+ * #define COREUARTAPB0_BASE_ADDR 0xC3000000UL
+ *
+ * UART_instance_t g_uart;
+ * int main()
+ * {
+ * UART_init(&g_uart, COREUARTAPB0_BASE_ADDR,
+ BAUD_VALUE_57600, (DATA_8_BITS | EVEN_PARITY));
+ * }
+ * @endcode
+ */
+void
+UART_init
+(
+ UART_instance_t * this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ * The function UART_send() is used to transmit data. It transfers the contents
+ * of the transmitter data buffer, passed as a function parameter, into the
+ * UART's hardware transmitter FIFO. It returns when the full content of the
+ * transmitter data buffer has been transferred to the UART's transmitter FIFO.
+ *
+ * Note: you cannot assume that the data you are sending using this function has
+ * been received at the other end by the time this function returns. The actual
+ * transmit over the serial connection will still be taking place at the time of
+ * the function return. It is safe to release or reuse the memory used as the
+ * transmit buffer once this function returns.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * UART_instance_t structure which holds all data regarding
+ * this instance of the CoreUARTapbUART.
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer
+ * containing the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size, in bytes, of
+ * the data to be transmitted.
+ *
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\n\r\n\r\n\rUART_send() test message 1"};
+ * UART_send(&g_uart,(const uint8_t *)&testmsg1,sizeof(testmsg1));
+ * @endcode
+ */
+void
+UART_send
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ * The function UART_fill_tx_fifo() fills the UART's transmitter hardware FIFO
+ * with the data found in the transmitter buffer that is passed in as a
+ * function parameter. The function returns either when the FIFO is full or
+ * when the complete contents of the transmitter buffer have been copied into
+ * the FIFO. It returns the number of bytes copied into the UART's transmitter
+ * hardware FIFO. This function is intended to be used as part of
+ * interrupt-driven transmission.
+ *
+ * Note: You cannot assume that the data you transmit using this function has
+ * been received at the other end by the time this function returns.
+ * The actual transmission over the serial connection will still be
+ * taking place at the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the UART.
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer
+ * containing the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes, of the data
+ * to be transmitted.
+ * @return This function returns the number of bytes copied
+ * into the UART's transmitter hardware FIFO.
+ *
+ * Example:
+ * @code
+ * void send_using_interrupt
+ * (
+ * uint8_t * pbuff,
+ * size_t tx_size
+ * )
+ * {
+ * size_t size_in_fifo;
+ * size_in_fifo = UART_fill_tx_fifo( &g_uart, pbuff, tx_size );
+ * }
+ * @endcode
+ */
+size_t
+UART_fill_tx_fifo
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ * The function UART_get_rx() reads the content of the UART's receiver hardware
+ * FIFO and stores it in the receiver buffer that is passed in as a function
+ * parameter. It copies either the full contents of the FIFO into the receiver
+ * buffer, or just enough data from the FIFO to fill the receiver buffer,
+ * dependent upon the size of the receiver buffer. The size of the receiver
+ * buffer is passed in as a function parameter. UART_get_rx() returns the number
+ * of bytes copied into the receiver buffer. If no data was received at the time
+ * the function is called, the function returns 0.
+ *
+ * Note: This function reads and accumulates the receiver status of the
+ * CoreUARTapb instance before reading each byte from the receiver's
+ * data register/FIFO. This allows the driver to maintain a sticky
+ * record of any receiver errors that occur as the UART receives each
+ * data byte; receiver errors would otherwise be lost after each read
+ * from the receiver's data register. A call to the UART_get_rx_status()
+ * function returns any receiver errors accumulated during the execution
+ * of the UART_get_rx() function.
+ * Note: When FIFO mode is disabled in the CoreUARTapb hardware configuration,
+ * the driver accumulates a sticky record of any parity errors, framing
+ * errors or overflow errors. When FIFO mode is enabled, the driver
+ * accumulates a sticky record of overflow errors only; in this case
+ * interrupts must be used to handle parity errors or framing errors.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the UART.
+ * @param rx_buffer The rx_buffer parameter is a pointer to a buffer where the
+ * received data will be copied.
+ * @param buff_size The buff_size parameter is the size of the receive buffer
+ * in bytes.
+ * @return This function returns the number of bytes copied into the
+ * receive buffer.
+ *
+ * Example:
+ * @code
+ * #define MAX_RX_DATA_SIZE 256
+ *
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t rx_size = 0;
+ *
+ * rx_size = UART_get_rx( &g_uart, rx_data, sizeof(rx_data) );
+ * @endcode
+ */
+size_t
+UART_get_rx
+(
+ UART_instance_t * this_uart,
+ uint8_t * rx_buffer,
+ size_t buff_size
+);
+
+/***************************************************************************//**
+ * The function UART_polled_tx_string() is used to transmit a NULL ('\0')
+ * terminated string. Internally, it polls for the transmit ready status and
+ * transfers the text starting at the address pointed to by p_sz_string into
+ * the UART's hardware transmitter FIFO. It is a blocking function and returns
+ * only when the complete string has been transferred to the UART's transmit
+ * FIFO.
+ *
+ * Note: You cannot assume that the data you transmit using this function
+ * has been received at the other end by the time this function
+ * returns. The actual transmission over the serial connection will
+ * still be taking place at the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * UART_instance_t structure which holds
+ * all data regarding this instance of the UART.
+ * @param p_sz_string The p_sz_string parameter is a pointer to a buffer
+ * containing the NULL ('\0') terminated string to be
+ * transmitted.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\r\n\r\nUART_polled_tx_string() test message 1\0"};
+ * UART_polled_tx_string(&g_uart,(const uint8_t *)&testmsg1);
+ * @endcode
+ */
+void
+UART_polled_tx_string
+(
+ UART_instance_t * this_uart,
+ const uint8_t * p_sz_string
+);
+
+/***************************************************************************//**
+ * The UART_get_rx_status() function returns the receiver error status of the
+ * CoreUARTapb instance. It reads both the current error status of the receiver
+ * and the accumulated error status from preceding calls to the UART_get_rx()
+ * function and combines them using a bitwise OR. It returns the cumulative
+ * parity, framing and overflow error status of the receiver, since the
+ * previous call to UART_get_rx_status(), as an 8-bit encoded value.
+ *
+ * Note: The UART_get_rx() function reads and accumulates the receiver status
+ * of the CoreUARTapb instance before reading each byte from the
+ * receiver's data register/FIFO. The driver maintains a sticky record
+ * of the cumulative error status, which persists after the
+ * UART_get_rx() function returns. The UART_get_rx_status() function
+ * clears this accumulated record of receiver errors before returning.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance
+ * of the UART.
+ * @return This function returns the UART receiver error status as
+ * an 8-bit encoded value. The returned value is 0 if no
+ * receiver errors occurred. The driver provides a set of
+ * bit mask constants which should be compared with and/or
+ * used to mask the returned value to determine the
+ * receiver error status.
+ * When the return value is compared to the following bit
+ * masks, a non-zero result indicates that the
+ * corresponding error occurred:
+ * UART_APB_PARITY_ERROR (bit mask = 0x01)
+ * UART_APB_OVERFLOW_ERROR (bit mask = 0x02)
+ * UART_APB_FRAMING_ERROR (bit mask = 0x04)
+ * When the return value is compared to the following bit
+ * mask, a non-zero result indicates that no error occurred:
+ * UART_APB_NO_ERROR (0x00)
+ *
+ * Example:
+ * @code
+ * UART_instance_t g_uart;
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t err_status;
+ * err_status = UART_get_err_status(&g_uart);
+ *
+ * if(UART_APB_NO_ERROR == err_status )
+ * {
+ * rx_size = UART_get_rx( &g_uart, rx_data, MAX_RX_DATA_SIZE );
+ * }
+ * @endcode
+ */
+uint8_t
+UART_get_rx_status
+(
+ UART_instance_t * this_uart
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_UART_APB_H */
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..8651f0c
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * @file coreuartapb_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreUARTapb register definitions
+ */
+
+#ifndef __CORE_UART_APB_REGISTERS
+#define __CORE_UART_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * TxData register details
+ */
+#define TXDATA_REG_OFFSET 0x0u
+
+/*
+ * TxData bits.
+ */
+#define TXDATA_OFFSET 0x0u
+#define TXDATA_MASK 0xFFu
+#define TXDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * RxData register details
+ */
+#define RXDATA_REG_OFFSET 0x4u
+
+/*
+ * RxData bits.
+ */
+#define RXDATA_OFFSET 0x4u
+#define RXDATA_MASK 0xFFu
+#define RXDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * ControReg1 register details
+ */
+#define CTRL1_REG_OFFSET 0x8u
+
+/*
+ * Baud value (Lower 8-bits)
+ */
+#define CTRL1_BAUDVALUE_OFFSET 0x8u
+#define CTRL1_BAUDVALUE_MASK 0xFFu
+#define CTRL1_BAUDVALUE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * ControReg2 register details
+ */
+#define CTRL2_REG_OFFSET 0xCu
+
+/*
+ * Bit length
+ */
+#define CTRL2_BIT_LENGTH_OFFSET 0xCu
+#define CTRL2_BIT_LENGTH_MASK 0x01u
+#define CTRL2_BIT_LENGTH_SHIFT 0u
+
+/*
+ * Parity enable.
+ */
+#define CTRL2_PARITY_EN_OFFSET 0xCu
+#define CTRL2_PARITY_EN_MASK 0x02u
+#define CTRL2_PARITY_EN_SHIFT 1u
+
+/*
+ * Odd/even parity selection.
+ */
+#define CTRL2_ODD_EVEN_OFFSET 0xCu
+#define CTRL2_ODD_EVEN_MASK 0x04u
+#define CTRL2_ODD_EVEN_SHIFT 2u
+
+/*
+ * Baud value (Higher 5-bits)
+ */
+#define CTRL2_BAUDVALUE_OFFSET 0xCu
+#define CTRL2_BAUDVALUE_MASK 0xF8u
+#define CTRL2_BAUDVALUE_SHIFT 3u
+
+/*------------------------------------------------------------------------------
+ * StatusReg register details
+ */
+#define StatusReg_REG_OFFSET 0x10u
+
+#define STATUS_REG_OFFSET 0x10u
+
+/*
+ * Transmit ready.
+ */
+#define STATUS_TXRDY_OFFSET 0x10u
+#define STATUS_TXRDY_MASK 0x01u
+#define STATUS_TXRDY_SHIFT 0u
+
+/*
+ * Receive full.
+ */
+#define STATUS_RXFULL_OFFSET 0x10u
+#define STATUS_RXFULL_MASK 0x02u
+#define STATUS_RXFULL_SHIFT 1u
+
+/*
+ * Parity error.
+ */
+#define STATUS_PARITYERR_OFFSET 0x10u
+#define STATUS_PARITYERR_MASK 0x04u
+#define STATUS_PARITYERR_SHIFT 2u
+
+/*
+ * Overflow.
+ */
+#define STATUS_OVERFLOW_OFFSET 0x10u
+#define STATUS_OVERFLOW_MASK 0x08u
+#define STATUS_OVERFLOW_SHIFT 3u
+
+/*
+ * Frame Error.
+ */
+#define STATUS_FRAMERR_OFFSET 0x10u
+#define STATUS_FRAMERR_MASK 0x10u
+#define STATUS_FRAMERR_SHIFT 4u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_UART_APB_REGISTERS */
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..d57f2ae
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * (c) Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..c4e7f3c
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Sub System(MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ The major features provided by the Mi-V uDMA driver are:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ the call to MIV_uDMA_init(), MIV_uDMA_config() function for Mi-V uDMA
+ instance in the design.
+ The μDMA can operate in two possible transfer configurations:
+
+ AHBL Read –> AHBL Write:
+ In this configuration, the μDMA reads data from the source memory over an
+ AHBL (Mirrored Main/Initiator) read interface and writes data to the
+ destination memory over an AHBL (Mirrored Main/Initiator) write interface.
+
+ AHBL Read –> TAS Write:
+ In this configuration, the μDMA reads data from the source memory over an
+ AHBL (Mirrored Main/Initiator) read interface and writes data to the
+ destination memory over the TAS (Mirrored Main/Initiator) write interface.
+
+ The AHBL Read -> TAS Write configuration is out of scope for this driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System(MIV_ESS) is a single channel
+ uDMA module that allows peripherals to perform read write operations between
+ source and destination memory. The Mi-V uDMA driver is generally used in
+ interrupt driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine(ISR) which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR will reset the Mi-V uDMA controller.
+ Once the Mi-V uDMA transfer completes, Mi-V uDMA retires. To
+ initiate another transaction, Mi-V uDMA will have to be configured again.
+
+ The operation of the Mi-V uDMA driver can be divided into following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset transfer
+
+ ### Initialization and configuration
+ Mi-V uDMA is first initialized by a call to MIV_uDMA_init(). This function
+ initializes the instance of Mi-V uDMA with base address. The MIV_uDMA_init()
+ function must be called before calling any other Mi-V uDMA driver functions.
+
+ The Mi-V uDMA is configured by a call to MIV_uDMA_config(). This function
+ will configure the source_addr and dest_addr registers of the Mi-V uDMA with
+ source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfer of Mi-V uDMA.
+
+ ### Start and Reset transfer
+ Once the Mi-V uDMA is configured, the transfers can be started with a call to
+ MIV_uDMA_start(). Once the Mi-V uDMA transfer is started, it can not be
+ aborted and the status of the transfer should be read from the ISR by a call
+ to MIV_uDMA_read_status().
+
+ The Mi-V uDMA can be reset to the default state by calling MIV_uDMA_reset()
+ function. After performing reset operation, the Mi-V uDMA should be
+ re-configured to perform transfer since MIV_uDMA_reset() resets the Mi-V uDMA
+ controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * Mi-V uDMA instant structure.
+ * This structure will hold the base of Mi-V uDMA module which is used in the
+ * other functions in the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() assigns the base address of Mi-V uDMA module to the
+ * uDMA instance structure.
+ * This address is used in later part of the driver to access the uDMA registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size
+ * and IRQ config register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure which
+ * holds the base address of Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA
+ *
+ * @param src_addr
+ * Source address of memory from which the uDMA will read the data.
+ *
+ * @param dest_addr
+ * Destination address where the data will be written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer
+ *
+ * @param irq_config
+ * uDMA IRQ Configuration.
+ *
+ * When set, the IRQ is asserted when and error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ *
+ * When clear, the IRQ is only asserted when an error occurs during a uDMA
+ * transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure which
+ * holds the base address of Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() is used to clear the uDMA interrupt and reset the uDMA
+ * transfer.
+ *
+ * This function should be called from interrupt handler and it will reset the
+ * values set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure which
+ * holds the base address of Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() will be used to status of the uDMA transfer. When
+ * Interrupt is enabled this function can be called from the interrupt handler
+ * to know the reason of uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure which
+ * holds the base address of Mi-V uDMA module.
+ *
+ * @return
+ * Return value will indicate error of busy status of the uDMA channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/miv-rv32-udma/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/miv-rv32-udma/src/platform/hal/cpu_types.h b/miv-rv32-udma/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/cpu_types.h
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file cpu_types.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Type definitions which can be commonly used by the fabric-ip drivers.
+ *
+ */
+#ifndef __CPU_TYPES_H
+#define __CPU_TYPES_H 1
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int size_t;
+
+/*------------------------------------------------------------------------------
+ * addr_t: address type.
+ * Used to specify the address of peripherals present in the processor's memory
+ * map.
+ */
+typedef unsigned int addr_t;
+
+/*------------------------------------------------------------------------------
+ * psr_t: processor state register.
+ * Used by HAL_disable_interrupts() and HAL_restore_interrupts() to store the
+ * processor's state between disabling and restoring interrupts.
+ */
+typedef unsigned int psr_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CPU_TYPES_H */
+
diff --git a/miv-rv32-udma/src/platform/hal/hal.h b/miv-rv32-udma/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hal.h
@@ -0,0 +1,235 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * @file hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware abstraction layer functions for peripheral register accesses.
+ *
+ */
+#ifndef __HAL_H
+#define __HAL_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cpu_types.h"
+#include "hw_reg_access.h"
+#include "hal_assert.h"
+/***************************************************************************//**
+ * Enable all interrupts at the processor level.
+ */
+void HAL_enable_interrupts( void );
+
+/***************************************************************************//**
+ * Disable all interrupts at the processor core level.
+ * Return the interrupts enable state before disabling occurred so that it can
+ * later be restored.
+ */
+psr_t HAL_disable_interrupts( void );
+
+/***************************************************************************//**
+ * Restore the interrupts enable state at the processor core level.
+ * This function is normally passed the value returned from a previous call to
+ * HAL_disable_interrupts().
+ */
+void HAL_restore_interrupts( psr_t saved_psr );
+
+/***************************************************************************//**
+ */
+#define FIELD_OFFSET(FIELD_NAME) (FIELD_NAME##_OFFSET)
+#define FIELD_SHIFT(FIELD_NAME) (FIELD_NAME##_SHIFT)
+#define FIELD_MASK(FIELD_NAME) (FIELD_NAME##_MASK)
+
+/***************************************************************************//**
+ * The macro HAL_set_32bit_reg() allows writing a 32 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint32_t containing the value to write.
+ */
+#define HAL_set_32bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_32bit_reg() is used to read the value of a 32 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint32_t value.
+ */
+#define HAL_get_32bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)) ))
+
+/***************************************************************************//**
+ * The macro HAL_set_32bit_reg_field() is used to write a field within a
+ * 32 bits wide register. The field written can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint32_t containing the field value to write.
+ */
+#define HAL_set_32bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_32bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_32bit_reg_field() is used to read a register field from
+ * within a 32 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint32_t value.
+ */
+#define HAL_get_32bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_32bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+/***************************************************************************//**
+ * The macro HAL_set_16bit_reg() allows writing a 16 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint_fast16_t containing the value to write.
+ */
+#define HAL_set_16bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_16bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_16bit_reg() is used to read the value of a 16 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint16_t value.
+ */
+#define HAL_get_16bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_16bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))
+
+/***************************************************************************//**
+ * The macro HAL_set_16bit_reg_field() is used to write a field within a
+ * 16 bits wide register. The field written can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint16_t containing the field value to write.
+ */
+#define HAL_set_16bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_16bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_16bit_reg_field() is used to read a register field from
+ * within a 8 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint16_t value.
+ */
+#define HAL_get_16bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_16bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+/***************************************************************************//**
+ * The macro HAL_set_8bit_reg() allows writing a 8 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint_fast8_t containing the value to write.
+ */
+#define HAL_set_8bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_8bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_8bit_reg() is used to read the value of a 8 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint8_t value.
+ */
+#define HAL_get_8bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_8bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))
+
+/***************************************************************************//**
+ */
+#define HAL_set_8bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_8bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_8bit_reg_field() is used to read a register field from
+ * within a 8 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint8_t value.
+ */
+#define HAL_get_8bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_8bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*HAL_H*/
+
diff --git a/miv-rv32-udma/src/platform/hal/hal_assert.h b/miv-rv32-udma/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..8e0c747
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hal_assert.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file hal_assert.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief HAL assert functions
+ */
+#ifndef __HAL_ASSERT_HEADER
+#define __HAL_ASSERT_HEADER 1
+#define NDEBUG 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+/***************************************************************************//**
+ * HAL_ASSERT() is defined out when the NDEBUG symbol is used.
+ ******************************************************************************/
+#define HAL_ASSERT(CHECK)
+
+#else
+
+/***************************************************************************//**
+ * Default behavior for HAL_ASSERT() macro:
+ *------------------------------------------------------------------------------
+ The behavior is toolchain specific and project setting specific.
+ ******************************************************************************/
+#define HAL_ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG */
+#endif /*__GNUC__*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __HAL_ASSERT_HEADER */
+
diff --git a/miv-rv32-udma/src/platform/hal/hal_irq.c b/miv-rv32-udma/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..6fe7fce
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file hal_irq.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Legacy interrupt control functions for the Microchip driver library
+ * hardware abstraction layer.
+ *
+ */
+#include "hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void HAL_enable_interrupts(void) {
+ MRV_enable_interrupts();
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+psr_t HAL_disable_interrupts(void) {
+ psr_t psr;
+ psr = read_csr(mstatus);
+ MRV_disable_interrupts();
+ return(psr);
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void HAL_restore_interrupts(psr_t saved_psr) {
+ write_csr(mstatus, saved_psr);
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/miv-rv32-udma/src/platform/hal/hw_macros.h b/miv-rv32-udma/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..ed2c681
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file hw_macros.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware registers access macros.
+ *
+ * THE MACROS DEFINED IN THIS FILE ARE DEPRECATED. DO NOT USE FOR NEW
+ * DEVELOPMENT.
+ *
+ * These macros are used to access peripheral registers. They allow access to
+ * 8, 16 and 32 bit wide registers. All accesses to peripheral registers should
+ * be done through these macros in order to ease porting across different
+ * processors/bus architectures.
+ *
+ * Some of these macros also allow access to a specific register field.
+ *
+ */
+#ifndef __HW_REGISTER_MACROS_H
+#define __HW_REGISTER_MACROS_H 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * 32 bits registers access:
+ */
+#define HW_get_uint32_reg(BASE_ADDR, REG_OFFSET) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint32_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint32_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint32_t) \
+ ( \
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint32_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint32_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 32 bits memory access:
+ */
+#define HW_get_uint32(BASE_ADDR) (*((uint32_t volatile *)(BASE_ADDR)))
+
+#define HW_set_uint32(BASE_ADDR, VALUE) (*((uint32_t volatile *)(BASE_ADDR)) = (VALUE))
+
+/*------------------------------------------------------------------------------
+ * 16 bits registers access:
+ */
+#define HW_get_uint16_reg(BASE_ADDR, REG_OFFSET) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint16_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint16_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint16_t) \
+ ( \
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint16_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint16_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 8 bits registers access:
+ */
+#define HW_get_uint8_reg(BASE_ADDR, REG_OFFSET) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint8_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint8_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint8_t) \
+ ( \
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint8_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint8_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 8 bits memory access:
+ */
+#define HW_get_uint8(BASE_ADDR) (*((uint8_t volatile *)(BASE_ADDR)))
+
+#define HW_set_uint8(BASE_ADDR, VALUE) (*((uint8_t volatile *)(BASE_ADDR)) = (VALUE))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif /* __HW_REGISTER_MACROS_H */
+
diff --git a/miv-rv32-udma/src/platform/hal/hw_reg_access.S b/miv-rv32-udma/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..f4aa0a0
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file hw_reg_access.S
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware registers access functions.
+ * The implementation of these function is platform and toolchain specific.
+ * The functions declared here are implemented using assembler as part of the
+ * processor/toolchain specific HAL. This implementation is for the combination
+ * of the 32 bit RISC-V processors and GNU tool chain.
+ *
+ */
+
+.section .text
+ .globl HW_set_32bit_reg
+ .globl HW_get_32bit_reg
+ .globl HW_set_32bit_reg_field
+ .globl HW_get_32bit_reg_field
+ .globl HW_set_16bit_reg
+ .globl HW_get_16bit_reg
+ .globl HW_set_16bit_reg_field
+ .globl HW_get_16bit_reg_field
+ .globl HW_set_8bit_reg
+ .globl HW_get_8bit_reg
+ .globl HW_set_8bit_reg_field
+ .globl HW_get_8bit_reg_field
+
+
+/***************************************************************************//**
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint32_t value
+ */
+HW_set_32bit_reg:
+ sw a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+
+ * @return 32 bits value read from the peripheral register.
+ */
+HW_get_32bit_reg:
+ lw a0, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint32_t mask
+ * a3: uint32_t value
+ */
+HW_set_32bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lw t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sw t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_32bit_reg_field is used to read the content of a field out of a
+ * 32 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint32_t mask
+ *
+ * @return 32 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_32bit_reg_field:
+ lw a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+/***************************************************************************//**
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint_fast16_t value
+ */
+HW_set_16bit_reg:
+ sh a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+
+ * @return 16 bits value read from the peripheral register.
+ */
+HW_get_16bit_reg:
+ lh a0, (a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast16_t mask
+ * a3: uint_fast16_t value
+ * @param value Value to be written in the specified field.
+ */
+HW_set_16bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lh t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sh t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_16bit_reg_field is used to read the content of a field from a
+ * 16 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast16_t mask
+ *
+ * @return 16 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_16bit_reg_field:
+ lh a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+/***************************************************************************//**
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint_fast8_t value
+ */
+HW_set_8bit_reg:
+ sb a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+
+ * @return 8 bits value read from the peripheral register.
+ */
+HW_get_8bit_reg:
+ lb a0, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr,
+ * a1: int_fast8_t shift
+ * a2: uint_fast8_t mask
+ * a3: uint_fast8_t value
+ */
+HW_set_8bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lb t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sb t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_8bit_reg_field is used to read the content of a field from a
+ * 8 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast8_t mask
+ *
+ * @return 8 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_8bit_reg_field:
+ lb a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+.end
diff --git a/miv-rv32-udma/src/platform/hal/hw_reg_access.h b/miv-rv32-udma/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1f6a551
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file hw_reg_access.S
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware registers access functions.
+ * The implementation of these function is platform and tool-chain specific.
+ * The functions declared here are implemented using assembler as part of the
+ * processor/tool-chain specific HAL. This implementation is for the combination
+ * of the 32 bit RISC-V processors and GNU tool chain.
+ *
+ */
+#ifndef __HW_REG_ACCESS
+#define __HW_REG_ACCESS
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cpu_types.h"
+/***************************************************************************//**
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_32bit_reg
+(
+ addr_t reg_addr,
+ uint32_t value
+);
+
+/***************************************************************************//**
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 32 bits value read from the peripheral register.
+ */
+uint32_t
+HW_get_32bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void
+HW_set_32bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint32_t mask,
+ uint32_t value
+);
+
+/***************************************************************************//**
+ * HW_get_32bit_reg_field is used to read the content of a field out of a
+ * 32 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 32 bits value containing the register field value specified
+ * as parameter.
+ */
+uint32_t
+HW_get_32bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint32_t mask
+);
+
+/***************************************************************************//**
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_16bit_reg
+(
+ addr_t reg_addr,
+ uint_fast16_t value
+);
+
+/***************************************************************************//**
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 16 bits value read from the peripheral register.
+ */
+uint16_t
+HW_get_16bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void HW_set_16bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast16_t mask,
+ uint_fast16_t value
+);
+
+/***************************************************************************//**
+ * HW_get_16bit_reg_field is used to read the content of a field from a
+ * 16 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 16 bits value containing the register field value specified
+ * as parameter.
+ */
+uint16_t HW_get_16bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast16_t mask
+);
+
+/***************************************************************************//**
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_8bit_reg
+(
+ addr_t reg_addr,
+ uint_fast8_t value
+);
+
+/***************************************************************************//**
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 8 bits value read from the peripheral register.
+ */
+uint8_t
+HW_get_8bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void HW_set_8bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast8_t mask,
+ uint_fast8_t value
+);
+
+/***************************************************************************//**
+ * HW_get_8bit_reg_field is used to read the content of a field from a
+ * 8 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 8 bits value containing the register field value specified
+ * as parameter.
+ */
+uint8_t HW_get_8bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast8_t mask
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HW_REG_ACCESS */
+
diff --git a/miv-rv32-udma/src/platform/hal/readme.md b/miv-rv32-udma/src/platform/hal/readme.md
new file mode 100644
index 0000000..c756b34
--- /dev/null
+++ b/miv-rv32-udma/src/platform/hal/readme.md
@@ -0,0 +1,38 @@
+# hal folder
+
+
+The HAL folder hardware abstraction for the bare metal drivers for the fabric
+IP cores. The HAL folder contains files using a combination of C and assembly
+source code. This layer allows the fabric ip drivers to be used with any of the
+soft processors or the MSS hardened processors.
+
+The hal folder should be included in a your project under the platform directory.
+See location in the drawing below.
+
+The hal folder contains:
+
+* register access functions
+* assert macros
+
+### Project directory strucutre, showing where hal folder sits.
+
+ +---------+ +-----------+
+ | src +----->|application|
+ +---------+ | +-----------+
+ |
+ | +-----------+
+ +-->|middleware |
+ | +-----------+
+ |
+ | +-----------+ +---------+
+ +-->|platform +---->|drivers |
+ +-----------+ | +---------+
+ |
+ | +---------+
+ +->|hal |
+ | +---------+
+ |
+ | +---------+
+ +->|mpfs_hal |
+ +---------+
+
\ No newline at end of file
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..19df5fb
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-execute-in-place.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * image executing from a one address space whereas the data, sdata and stack
+ * sections are placed in another address space. This could be used in cases such
+ * as:
+ * 1) When using MIV_RV32, the reset vector points to the LSRAM at address
+ * 0x80000000 and the data, sdata, bss and stack sections are placed in the
+ * TCM region.
+ *
+ * 2) Executing from a Non Volatile memory. The actual memory will depend on
+ * the FPGA platform. For exameple, it could be the eNVM on SmartFusion2,
+ * Igloo2 or on-board non-volatile memory which supports code execution.
+ *
+ * NOTE: Modify the memory section addresses and the sizes according to your
+ * Libero design.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x80000000, LENGTH = 16k
+ ram (rwx) : ORIGIN = 0x80004000, LENGTH = 16k
+}
+
+STACK_SIZE = 1k; /* needs to be calculated for your application */
+HEAP_SIZE = 0; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > rom
+
+ .text : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.text.entry)))
+ . = ALIGN(0x10);
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } >rom
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } >ram AT>rom
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } >ram AT>rom
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..e0707df
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-ram.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * debug image executing in SRAM.
+ *
+ * This linker script assumes that a RAM is connected at on Mi-V soft processor
+ * memory space pointed by the reset vector address.
+ *
+ * NOTE : Modify the memory section address and the size according to your
+ * Libero design.
+ * For example:
+ * 1) If you want to download and step debug at a different RAM memory address in
+ * your design (For example TCM base address) than the one provided in this file.
+ * 2) The MIV_RV32, when used with MIV_ESS IP, provides ways to copy the executable
+ * HEX file from external Non-Volatile memory into the TCM at reset. In this
+ * case your executable must be linked to the TCM address.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 32k
+}
+
+STACK_SIZE = 2k; /* needs to be calculated for your application */
+HEAP_SIZE = 0k; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > ram
+
+ .text : ALIGN(0x10)
+ {
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } > ram
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } > ram
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } > ram
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_entry.S b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..a19a813
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,821 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_entry.S
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor vectors, trap handling and startup code.
+ *
+ */
+#ifndef ENTRY_S
+#define ENTRY_S
+
+#define A_EXTENSION_MASK 0x00000001u
+#define MTVEC_MODE_BIT_MASK 0x00000003u
+#define MTVEC_VECTORED_MODE_VAL 0x00000001u
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+ .section .entry, "ax"
+ .globl _start
+
+_start:
+ j handle_reset
+
+/* Some of the Mi-V soft IP cores support compressed 'C' extension. If the Mi-V
+ core in your design doesn't support 'C' extension and you enable 'C' extension
+ in firmware project compiler options, then it would result in a trap. For this
+ case, we are avoiding compressed instruction here so you can put a breakpoint
+ at the jump and you can at least look at mcause, mepc and get some hints
+ about the crash. */
+trap_entry:
+.option push
+.option norvc
+j generic_trap_handler
+.option pop
+ .word 0
+ .word 0
+
+sw_trap_entry:
+ j vector_sw_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+ .word 0
+ .word 0
+ .word 0
+
+tmr_trap_entry:
+ j vector_tmr_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+ .word 0
+ .word 0
+ .word 0
+
+ext_trap_entry:
+ j vector_ext_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+
+#ifndef MIV_LEGACY_RV32
+MGEUI_trap_entry:
+ j vector_MGEUI_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MGECI_trap_entry:
+ j vector_MGECI_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+
+MSYS_EI0_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_EI1_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_EI2_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_EI3_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_EI4_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_EI5_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+OPSRV_trap_entry:
+ j vector_OPSRV_IRQHandler
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ addi sp, sp, -32*REGBYTES
+.align 4
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+#ifdef MIV_LEGACY_RV32
+ jal handle_m_ext_interrupt
+#else
+ jal External_IRQHandler
+#endif /* MIV_LEGACY_RV32 */
+ j generic_restore
+
+#ifndef MIV_LEGACY_RV32
+vector_MGEUI_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_OPSRV_IRQHandler:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+ jal OPSRV_IRQHandler
+ j generic_restore
+#endif /* MIV_LEGACY_RV32 */
+
+generic_restore:
+ LREG x1, 0 * REGBYTES(sp)
+ LREG x2, 1 * REGBYTES(sp)
+ LREG x3, 2 * REGBYTES(sp)
+ LREG x4, 3 * REGBYTES(sp)
+ LREG x5, 4 * REGBYTES(sp)
+ LREG x6, 5 * REGBYTES(sp)
+ LREG x7, 6 * REGBYTES(sp)
+ LREG x8, 7 * REGBYTES(sp)
+ LREG x9, 8 * REGBYTES(sp)
+ LREG x10, 9 * REGBYTES(sp)
+ LREG x11, 10 * REGBYTES(sp)
+ LREG x12, 11 * REGBYTES(sp)
+ LREG x13, 12 * REGBYTES(sp)
+ LREG x14, 13 * REGBYTES(sp)
+ LREG x15, 14 * REGBYTES(sp)
+ LREG x16, 15 * REGBYTES(sp)
+ LREG x17, 16 * REGBYTES(sp)
+ LREG x18, 17 * REGBYTES(sp)
+ LREG x19, 18 * REGBYTES(sp)
+ LREG x20, 19 * REGBYTES(sp)
+ LREG x21, 20 * REGBYTES(sp)
+ LREG x22, 21 * REGBYTES(sp)
+ LREG x23, 22 * REGBYTES(sp)
+ LREG x24, 23 * REGBYTES(sp)
+ LREG x25, 24 * REGBYTES(sp)
+ LREG x26, 25 * REGBYTES(sp)
+ LREG x27, 26 * REGBYTES(sp)
+ LREG x28, 27 * REGBYTES(sp)
+ LREG x29, 28 * REGBYTES(sp)
+ LREG x30, 29 * REGBYTES(sp)
+ LREG x31, 30 * REGBYTES(sp)
+
+ addi sp, sp, 32*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+ csrr t0, misa
+ andi t0, t0, A_EXTENSION_MASK
+ bnez t0, ima_cores_setup /* Jump to IMA core handling */
+
+/* For MIV_RV32 cores the mtvec exception base address is fixed at Reset vector
+ address + 0x4. Check the mode bits. */
+ csrr t0, mtvec
+ andi t0, t0, MTVEC_MODE_BIT_MASK
+ li t1, MTVEC_VECTORED_MODE_VAL
+ bne t0, t1, ima_cores_setup /* Jump to IMA core handling */
+
+ /* When mode = 1 => this is vectored mode on MIV_RV32 core.
+ Verify that the trap_handler address matches the configuration in MTVEC */
+ csrr t0, mtvec
+ andi t0, t0, 0xFFFFFFFC
+ la t1, trap_entry
+ bne t0, t1, vector_address_not_matching
+ j generic_reset_handling
+
+ima_cores_setup:
+ la t0, trap_entry
+
+#ifdef MIV_LEGACY_RV32_VECTORED_INTERRUPTS
+ addi t0, t0, 0x01 /* Set the mode bit for IMA cores.
+ For MIV_RV32 cores this is done by configurator. */
+#endif
+ csrw mtvec, t0
+
+generic_reset_handling:
+/* Copy sdata section first so that the gp is set and linker relaxation can be
+ used */
+ la a4, __sdata_load
+ la a5, __sdata_start
+ la a6, __sdata_end
+ beq a4, a5, 1f /* Exit if source and dest are same */
+ beq a5, a6, 1f /* Exit if section start and end addresses are same */
+ call block_copy
+
+1:
+ /* initialize global pointer */
+ la gp, __global_pointer$
+
+.option pop
+
+/* Floating point support configuration */
+#ifdef __riscv_flen
+ csrr t0, mstatus
+ lui t1, 0xffffa
+ addi t1, t1, -1
+ and t0, t0, t1
+ lui t1, 0x4
+ or t1, t0, t1
+ csrw mstatus, t1
+
+ lui t0, 0x0
+ fscsr t0
+#endif
+ call initializations
+ /* Initialize stack pointer */
+ la sp, __stack_top
+
+ /* Jump into C code */
+ j _init
+
+/* Error: trap_entry is not at the expected address of reset_vector+mtvec offset
+ as configured in the MIV_RV32 core vectored mode */
+vector_address_not_matching:
+ ebreak
+
+initializations:
+/* Initialize the .bss section */
+ mv t0, ra /* Store ra for future use */
+ la a5, __bss_start
+ la a6, __bss_end
+ beq a5, a6, 1f /* Section start and end address are the same */
+ call zeroize_block
+
+1:
+/* Initialize the .sbss section */
+ la a5, __sbss_start
+ la a6, __sbss_end
+ beq a5, a6, 1f /* Section start and end address are the same */
+ call zeroize_block
+
+/* Clear heap */
+ la a5, __heap_start
+ la a6, __heap_end
+ beq a5, a6, 1f /* Section start and end address are the same */
+ call zeroize_block
+
+1:
+/* Copy data section */
+ la a4, __data_load
+ la a5, __data_start
+ la a6, __data_end
+ beq a4, a5, 1f /* Exit early if source and dest are same */
+ beq a5, a6, 1f /* Section start and end addresses are the same */
+ call block_copy
+
+1:
+ mv ra, t0 /* Retrieve ra */
+ ret
+
+zeroize_block:
+ bltu a6, a5, block_copy_error /* Error. End address is less than start */
+ or a7, a6, a5 /* Check if start or end is unalined */
+ andi a7, a7, 0x03u
+ bgtz a7, block_copy_error /* Unaligned addresses error*/
+zeroize_loop:
+ sw x0, 0(a5)
+ add a5, a5, __SIZEOF_POINTER__
+ blt a5, a6, zeroize_loop
+ ret
+
+block_copy:
+ bltu a6, a5, block_copy_error /* Error. End address is less than start */
+ or a7, a6, a5 /* Check if start or end is unalined */
+ andi a7, a7, 0x03u
+ bgtz a7, block_copy_error /* Unaligned addresses error*/
+block_copy_loop:
+ lw a7, 0(a4)
+ sw a7, 0(a5)
+ addi a5, a5, 0x04
+ addi a4, a4, 0x04
+ blt a5, a6, block_copy_loop
+ j block_copy_exit
+
+block_copy_error:
+ j block_copy_error
+
+block_copy_exit:
+ ret
+
+#endif /*ENTRY_S*/
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.c b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..8fa82b1
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Implementation of Hardware Abstraction Layer for Mi-V soft processors
+ *
+ */
+#include
+#include "miv_rv32_hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SUCCESS 0U
+#define ERROR 1U
+#define MASK_32BIT 0xFFFFFFFFu
+
+/*------------------------------------------------------------------------------
+ * Write in a sequence recommended by privileged spec to avoid spurious
+ * interrupts
+
+ # New comparand is in a1:a0.
+ li t0, -1
+ sw t0, mtimecmp # No smaller than old value.
+ sw a1, mtimecmp+4 # No smaller than new value.
+ sw a0, mtimecmp # New value.
+ */
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+
+extern void Software_IRQHandler(void);
+
+#ifdef MIV_LEGACY_RV32
+#define MTIME_PRESCALER 100UL
+/*------------------------------------------------------------------------------
+ *
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t External_1_IRQHandler(void);
+uint8_t External_2_IRQHandler(void);
+uint8_t External_3_IRQHandler(void);
+uint8_t External_4_IRQHandler(void);
+uint8_t External_5_IRQHandler(void);
+uint8_t External_6_IRQHandler(void);
+uint8_t External_7_IRQHandler(void);
+uint8_t External_8_IRQHandler(void);
+uint8_t External_9_IRQHandler(void);
+uint8_t External_10_IRQHandler(void);
+uint8_t External_11_IRQHandler(void);
+uint8_t External_12_IRQHandler(void);
+uint8_t External_13_IRQHandler(void);
+uint8_t External_14_IRQHandler(void);
+uint8_t External_15_IRQHandler(void);
+uint8_t External_16_IRQHandler(void);
+uint8_t External_17_IRQHandler(void);
+uint8_t External_18_IRQHandler(void);
+uint8_t External_19_IRQHandler(void);
+uint8_t External_20_IRQHandler(void);
+uint8_t External_21_IRQHandler(void);
+uint8_t External_22_IRQHandler(void);
+uint8_t External_23_IRQHandler(void);
+uint8_t External_24_IRQHandler(void);
+uint8_t External_25_IRQHandler(void);
+uint8_t External_26_IRQHandler(void);
+uint8_t External_27_IRQHandler(void);
+uint8_t External_28_IRQHandler(void);
+uint8_t External_29_IRQHandler(void);
+uint8_t External_30_IRQHandler(void);
+uint8_t External_31_IRQHandler(void);
+
+
+/*------------------------------------------------------------------------------
+ * RISC-V interrupt handler for external interrupts.
+ */
+uint8_t (* const ext_irq_handler_table[32])(void) =
+{
+
+ Invalid_IRQHandler,
+ External_1_IRQHandler,
+ External_2_IRQHandler,
+ External_3_IRQHandler,
+ External_4_IRQHandler,
+ External_5_IRQHandler,
+ External_6_IRQHandler,
+ External_7_IRQHandler,
+ External_8_IRQHandler,
+ External_9_IRQHandler,
+ External_10_IRQHandler,
+ External_11_IRQHandler,
+ External_12_IRQHandler,
+ External_13_IRQHandler,
+ External_14_IRQHandler,
+ External_15_IRQHandler,
+ External_16_IRQHandler,
+ External_17_IRQHandler,
+ External_18_IRQHandler,
+ External_19_IRQHandler,
+ External_20_IRQHandler,
+ External_21_IRQHandler,
+ External_22_IRQHandler,
+ External_23_IRQHandler,
+ External_24_IRQHandler,
+ External_25_IRQHandler,
+ External_26_IRQHandler,
+ External_27_IRQHandler,
+ External_28_IRQHandler,
+ External_29_IRQHandler,
+ External_30_IRQHandler,
+ External_31_IRQHandler
+};
+
+#else
+/*------------------------------------------------------------------------------
+ * Interrupt handlers as mapped into the MIE register of the MIV_RV32
+ */
+extern void External_IRQHandler(void);
+extern void MGEUI_IRQHandler(void);
+extern void MGECI_IRQHandler(void);
+extern void MSYS_EI0_IRQHandler(void);
+extern void MSYS_EI1_IRQHandler(void);
+extern void MSYS_EI2_IRQHandler(void);
+extern void MSYS_EI3_IRQHandler(void);
+extern void MSYS_EI4_IRQHandler(void);
+extern void MSYS_EI5_IRQHandler(void);
+extern void OPSRV_IRQHandler(void);
+
+#endif
+
+/*------------------------------------------------------------------------------
+ * Increment value for the mtimecmp register in order to achieve a system tick
+ * interrupt as specified through the MRV_systick_config() function.
+ */
+static uint64_t g_systick_increment = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+
+ g_systick_increment = (uint64_t)(ticks) / MTIME_PRESCALER;
+
+ if (g_systick_increment > 0U)
+ {
+
+#ifndef MIV_RV32_EXT_TIMECMP
+ WRITE_MTIMECMP(MRV_read_mtime() + g_systick_increment)
+#endif
+ set_csr(mie, MIP_MTIP);
+ MRV_enable_interrupts();
+
+ ret_val = SUCCESS;
+ }
+
+ return ret_val;
+}
+
+/*------------------------------------------------------------------------------
+ * RISC-V interrupt handler for machine timer interrupts.
+ */
+void handle_m_timer_interrupt(void)
+{
+#ifndef MIV_RV32_EXT_TIMECMP
+ WRITE_MTIMECMP(MRV_read_mtime() + g_systick_increment)
+#endif
+ SysTick_Handler();
+}
+
+/*------------------------------------------------------------------------------
+ * RISC-V interrupt handler for software interrupts.
+ */
+#ifdef MIV_LEGACY_RV32
+void handle_m_ext_interrupt(void)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ uint32_t int_num = PLIC->TARGET[hart_id].CLAIM_COMPLETE;
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+
+ if (0u !=int_num)
+ {
+ disable = ext_irq_handler_table[int_num]();
+
+ PLIC->TARGET[hart_id].CLAIM_COMPLETE = int_num;
+
+ if(EXT_IRQ_DISABLE == disable)
+ {
+ MRV_PLIC_disable_irq((IRQn_Type)int_num);
+ }
+ }
+}
+#endif
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT))
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER))
+ {
+ handle_m_timer_interrupt();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT))
+ {
+#ifdef MIV_LEGACY_RV32
+ handle_m_ext_interrupt();
+#else
+ External_IRQHandler();
+#endif
+ }
+#ifndef MIV_LEGACY_RV32
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI0))
+ {
+ MSYS_EI0_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI1))
+ {
+ MSYS_EI1_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI2))
+ {
+ MSYS_EI2_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI3))
+ {
+ MSYS_EI3_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI4))
+ {
+ MSYS_EI4_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MSYS_EI5))
+ {
+ MSYS_EI5_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == OPSRV_REG))
+ {
+ OPSRV_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MGEUI))
+ {
+ MGEUI_IRQHandler();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == MGECI))
+ {
+ MGECI_IRQHandler();
+ }
+#endif
+
+ else
+ {
+#ifndef NDEBUG
+ /*
+ Arguments supplied to this function are mcause, mepc (exception PC) and
+ stack pointer.
+ Based on privileged-isa specification mcause values and meanings are:
+
+ 0 Instruction address misaligned (mtval/mtval is the address)
+ 1 Instruction access fault (mtval/mtval is the address)
+ 2 Illegal instruction (mtval/mtval contains the
+ offending instruction opcode)
+ 3 Breakpoint
+ 4 Load address misaligned (mtval/mtval is the address)
+ 5 Load address fault (mtval/mtval is the address)
+ 6 Store/AMO address fault (mtval/mtval is the address)
+ 7 Store/AMO access fault (mtval/mtval is the address)
+ 8 Environment call from U-mode
+ 9 Environment call from S-mode
+ A Environment call from M-mode
+ B Instruction page fault
+ C Load page fault (mtval/mtval is the address)
+ E Store page fault (mtval/mtval is the address)
+
+ # Please note: mtval is the newer name for register mbadaddr
+ # If you get a compile failure here, use the older name.
+ # At this point, both are supported in latest compiler, older compiler
+ # versions only support mbadaddr.
+ # See: https://github.com/riscv/riscv-gcc/issues/133
+ */
+
+ /* interrupt pending */
+ uintptr_t mip = read_csr(mip);
+
+ /* additional info and meaning depends on mcause */
+ uintptr_t mtval = read_csr(mtval);
+
+ /* trap vector */
+ uintptr_t mtvec = read_csr(mtvec);
+
+ /* temporary, sometimes might hold temporary value of a0 */
+ uintptr_t mscratch = read_csr(mscratch);
+
+ /* status contains many smaller fields: */
+ uintptr_t mstatus = read_csr(mstatus);
+
+ /* PC value when the exception was taken*/
+ uintptr_t mmepc = read_csr(mepc);
+
+ /* breakpoint */
+ __asm__("ebreak");
+#else
+ _exit(1 + mcause);
+#endif
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.h b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..7231610
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,521 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * Return value from External IRQ handler. This will be used to disable the
+ * External interrupt.
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+/***************************************************************************//**
+ * System tick handler. This handler function gets called when the Machine
+ * timer interrupt asserts. An implementation of this function should be
+ * provided by the application to implement the application specific machine
+ * timer interrupt handling. If application does not provide such implementation
+ * the weakly linked handler stub function implemented in riscv_hal_stubs.c gets
+ * linked.
+ */
+void SysTick_Handler(void);
+
+/***************************************************************************//**
+ * System timer tick configuration.
+ * Configures the machine timer to generate a system tick interrupt at regular
+ * intervals.
+ * Takes the number of system clock ticks between interrupts.
+ *
+ * Returns 0 if successful.
+ * Returns 1 if the interrupt interval cannot be achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+
+#ifdef MIV_LEGACY_RV32
+#define MSIP (*(uint32_t*)0x44000000UL)
+#define MTIMECMP (*(uint32_t*)0x44004000UL)
+#define MTIMECMPH (*(uint32_t*)0x44004004UL)
+#define MTIME (*(uint32_t*)0x4400BFF8UL)
+#define MTIMEH (*(uint32_t*)0x4400BFFCUL)
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x44000000UL
+
+#else
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+/* OPSRV stands for "Offload Processor Subsystem for RISC-V" (OPSRV) on the
+ * MIV_RV32 IP core. Please see the handbook for more details. */
+
+/* TCM ECC correctable error irq enable mask value */
+#define OPSRV_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define OPSRV_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define OPSRV_AXI_WR_RESP_IRQ 0x10u
+
+#define OPSRV_BASE_ADDR 0x00006000UL
+
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not being supported by MIV_RV32 v3.0*/
+ volatile uint32_t reserved0[3];
+ volatile uint32_t irq_en; /*offset 0x10*/
+ volatile uint32_t irq_pend;
+ volatile uint32_t reserved1[2];
+ volatile uint32_t soft_reg; /*offset 0x20*/
+} OPSRV_Type;
+
+#define OPSRV ((OPSRV_Type *)OPSRV_BASE_ADDR)
+
+#define EXT_INTR_SOURCES 1
+
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+
+/* On MIV_RV32IMC v2.0 and v2.1 MTIME_PRESCALER is not defined and using this
+ * definition will result in crash. For those core use the definition as below
+ * #define MTIME_PRESCALER 100u
+ */
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+#else
+#define MTIME HAL_ASSERT(0);
+#endif
+
+/* These definitions are provided for convenient identification of the interrupts
+ * in the MIE/MIP registers.
+ * Apart from the standard software, timer and external interrupts, the names
+ * of the additional interrupts correspond to the names as used in the MIV_RV32
+ * handbook. Please refer the MIV_RV32 handbook for more details.
+ * */
+#define MRV32_SOFT_IRQn MIE_3_IRQn
+#define MRV32_TIMER_IRQn MIE_7_IRQn
+#define MRV32_EXT_IRQn MIE_11_IRQn
+
+/*==============================================================================
+ * Interrupt numbers:
+ * This enum represents the interrupt enable bits in the MIE register.
+ */
+enum
+{
+ MIE_0_IRQn = (0x01u),
+ MIE_1_IRQn = (0x01u<<1u),
+ MIE_2_IRQn = (0x01u<<2u),
+ MIE_3_IRQn = (0x01u<<3u), /*MSIE*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE*/
+ MIE_12_IRQn = (0x01u<<12u),
+ MIE_13_IRQn = (0x01u<<13u),
+ MIE_14_IRQn = (0x01u<<14u),
+ MIE_15_IRQn = (0x01u<<15u),
+ MIE_16_IRQn = (0x01u<<16u), /*MGEUIE*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE*/
+ MIE_18_IRQn = (0x01u<<18u),
+ MIE_19_IRQn = (0x01u<<19u),
+ MIE_20_IRQn = (0x01u<<20u),
+ MIE_21_IRQn = (0x01u<<21u),
+ MIE_22_IRQn = (0x01u<<22u),
+ MIE_23_IRQn = (0x01u<<23u),
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_EIE0*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_EIE1*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_EIE2*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_EIE3*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_EIE4*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_EIE5*/
+ MIE_30_IRQn = (0x01u<<30u) /*OPSRV_IRQ_IE*/
+
+} MRV_LOCAL_IRQn_Type;
+
+#ifndef MIV_LEGACY_RV32
+#define MRV32_MGEUIE_IRQn MIE_16_IRQn
+#define MRV32_MGECIE_IRQn MIE_17_IRQn
+#define MRV32_MSYS_EIE0_IRQn MIE_24_IRQn
+#define MRV32_MSYS_EIE1_IRQn MIE_25_IRQn
+#define MRV32_MSYS_EIE2_IRQn MIE_26_IRQn
+#define MRV32_MSYS_EIE3_IRQn MIE_27_IRQn
+#define MRV32_MSYS_EIE4_IRQn MIE_28_IRQn
+#define MRV32_MSYS_EIE5_IRQn MIE_29_IRQn
+#define MRV32_MSYS_OPSRV_IRQn MIE_30_IRQn
+
+/***************************************************************************//**
+ Enable OPSRV interrupt. Parameter takes logical OR of following values
+ #define OPSRV_TCM_ECC_CE_IRQ 0x01u
+ #define OPSRV_TCM_ECC_UCE_IRQ 0x02u
+ #define OPSRV_AXI_WR_RESP_IRQ 0x10u
+ */
+static inline void MRV32_opsrv_enable_irq(uint32_t irq_mask)
+{
+ OPSRV->irq_en = irq_mask;
+}
+
+/***************************************************************************//**
+ Disable OPSRV interrupt. Parameter takes logical OR of following values
+ #define OPSRV_TCM_ECC_CE_IRQ 0x01u
+ #define OPSRV_TCM_ECC_UCE_IRQ 0x02u
+ #define OPSRV_AXI_WR_RESP_IRQ 0x10u
+ */
+static inline void MRV32_opsrv_disable_irq(uint32_t irq_mask)
+{
+ OPSRV->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ Clear OPSRV interrupt. Parameter takes logical OR of following values
+ #define OPSRV_TCM_ECC_CE_IRQ 0x01u
+ #define OPSRV_TCM_ECC_UCE_IRQ 0x02u
+ #define OPSRV_AXI_WR_RESP_IRQ 0x10u
+ */
+static inline void MRV32_opsrv_clear_irq(uint32_t irq_mask)
+{
+ OPSRV->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ * The function MRV32_is_gpr_ded() returns the core_gpr_ded_reset_reg bit value.
+ * When ECC is enabled, the core_gpr_ded_reset_reg is set when the core was
+ * reset due to GPR DED error.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((OPSRV->soft_reg & 0x04u) >> 0x02u);
+}
+
+/***************************************************************************//**
+ * The function MRV32_clear_gpr_ded() can be used to clear the
+ * core_gpr_ded_reset_reg bit. When ECC is enabled, the core_gpr_ded_reset_reg
+ * is set when the core was previously reset due to GPR DED error.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ OPSRV->soft_reg &= ~0x04u;
+}
+
+/***************************************************************************//**
+ * The function MRV32_enable_parity_check() is used to enable parity check on
+ * the TCM and it's interface transactions. This feature is not available on
+ * MIV_RV32 v3.0.100 soft processor core.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ OPSRV->cfg |= 0x01u;
+}
+
+/***************************************************************************//**
+ * The function MRV32_disable_parity_check() is used to disable parity check on
+ * the TCM and it's interface transactions.
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ OPSRV->cfg &= ~0x01u;
+}
+
+/***************************************************************************//**
+ * The function MRV32_cpu_soft_reset() is used to cause a soft cpu reset on
+ * the MIV_RV32 soft processor core.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ OPSRV->soft_reg &= ~0x01u;
+}
+
+/***************************************************************************//**
+ Clear GPR ECC Uncorrectable interrupt. MGEUI interrupt is available only when
+ ECC is enabled in MIV_RV32 IP configurator.
+ */
+static inline void MRV32_mgeui_clear_irq(uint32_t irq_mask)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ Clear GPR ECC correctable interrupt. MGECI interrupt is available only when
+ ECC is enabled in MIV_RV32 IP configurator.
+ */
+static inline void MRV32_mgeci_clear_irq(uint32_t irq_mask)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ When ECC is enabled for the GPRs and if that data has a single bit error then
+ the data coming out of the ECC block will be corrected and will not have the
+ error but the data source will still have the error.
+ The ECC block does not write back corrected data to memory.
+ Therefore, if data has a single bit error, then the corrected data should be
+ written back to prevent the single bit error from becoming a double bit error.
+ The MRV32_clear_gpr_ecc_errors() can be used for that.
+
+ Clear the pending interrupt bit after this using MRV32_mgeci_clear_irq()
+ function to complete the ECC error handling.
+ */
+static inline void MRV32_clear_gpr_ecc_errors(void)
+{
+ uint32_t temp;
+
+ __asm__ __volatile__ (
+ "sw x31, %0"
+ :"=m" (temp));
+
+ __asm__ volatile (
+ "mv x31, x1;"
+ "mv x1, x31;"
+
+ "mv x31, x2;"
+ "mv x2, x31;"
+
+ "mv x31, x3;"
+ "mv x3, x31;"
+
+ "mv x31, x4;"
+ "mv x4, x31;"
+
+ "mv x31, x5;"
+ "mv x5, x31;"
+
+ "mv x31, x6;"
+ "mv x6, x31;"
+
+ "mv x31, x7;"
+ "mv x7, x31;"
+
+ "mv x31, x8;"
+ "mv x8, x31;"
+
+ "mv x31, x9;"
+ "mv x9, x31;"
+
+ "mv x31, x10;"
+ "mv x10, x31;"
+
+ "mv x31, x11;"
+ "mv x11, x31;"
+
+ "mv x31, x12;"
+ "mv x12, x31;"
+
+ "mv x31, x13;"
+ "mv x13, x31;"
+
+ "mv x31, x14;"
+ "mv x14, x31;"
+
+ "mv x31, x15;"
+ "mv x15, x31;"
+
+ "mv x31, x16;"
+ "mv x16, x31;"
+
+ "mv x31, x17;"
+ "mv x17, x31;"
+
+ "mv x31, x18;"
+ "mv x18, x31;"
+
+ "mv x31, x19;"
+ "mv x19, x31;"
+
+ "mv x31, x20;"
+ "mv x20, x31;"
+
+ "mv x31, x21;"
+ "mv x21, x31;"
+
+ "mv x31, x22;"
+ "mv x22, x31;"
+
+ "mv x31, x23;"
+ "mv x23, x31;"
+
+ "mv x31, x24;"
+ "mv x24, x31;"
+
+ "mv x31, x25;"
+ "mv x25, x31;"
+
+ "mv x31, x26;"
+ "mv x26, x31;"
+
+ "mv x31, x27;"
+ "mv x27, x31;"
+
+ "mv x31, x28;"
+ "mv x28, x31;"
+
+ "mv x31, x29;"
+ "mv x29, x31;"
+
+ "mv x31, x30;"
+ "mv x30, x31;");
+
+ __asm__ __volatile__ (
+ "lw x31, %0;"
+ :
+ :"m" (temp));
+}
+
+#endif
+
+/***************************************************************************//**
+ * Enable interrupts.
+ This function takes a mask value as input. For each set bit in the mask value,
+ corresponding interrupt bit in the MIE register is enabled.
+
+ MRV_enable_local_irq(MRV32_SOFT_IRQn |
+ MRV32_TIMER_IRQn |
+ MRV32_EXT_IRQn |
+ MRV32_MSYS_EIE0_IRQn |
+ MRV32_MSYS_OPSRV_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ * Disable interrupts.
+ This function takes a mask value as input. For each set bit in the mask value,
+ corresponding interrupt bit in the MIE register is disabled.
+
+ MRV_disable_local_irq(MRV32_SOFT_IRQn |
+ MRV32_TIMER_IRQn |
+ MRV32_EXT_IRQn |
+ MRV32_MSYS_EIE0_IRQn |
+ MRV32_MSYS_OPSRV_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif
+
+/***************************************************************************//**
+ * The function MRV_raise_soft_irq() raises a synchronous software interrupt
+ * by writing into the MSIP register.
+ */
+static inline void MRV_raise_soft_irq(void)
+{
+ set_csr(mie, MIP_MSIP); /* Enable software interrupt bit */
+
+#ifdef MIV_LEGACY_RV32
+ /* You need to make sure that the global interrupt is enabled */
+ MSIP = 0x01; /* raise soft interrupt */
+#else
+ /* Raise soft IRQ on MIV_RV32 processor */
+ OPSRV->soft_reg |= (1u << 1u);
+#endif
+}
+
+/***************************************************************************//**
+ * The function MRV_clear_soft_irq() clears a synchronous software interrupt
+ * by clearing the MSIP register.
+ */
+static inline void MRV_clear_soft_irq(void)
+{
+#ifdef MIV_LEGACY_RV32
+ MSIP = 0x00u; /* clear soft interrupt */
+#else
+ /* Clear soft IRQ on MIV_RV32 processor */
+ OPSRV->soft_reg &= ~(1u << 1u);
+#endif
+}
+
+/***************************************************************************//**
+ * The function MRV_enable_interrupts() enables all interrupts setting the
+ * machine mode interrupt enable bit in MSTATUS register.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ * The function MRV_disable_interrupts() disables all interrupts clearing the
+ * machine mode interrupt enable bit in MSTATUS register.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ * The function MRV_read_mtime() returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+#ifndef MIV_RV32_EXT_TIMER
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ hi = MTIMEH;
+ lo = MTIME;
+ } while(hi != MTIMEH);
+
+ return((((uint64_t)MTIMEH) << 32u) | lo);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_HAL_H */
+
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_init.c b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..e5f811f
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_init.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor memory section initializations and start-up code.
+ *
+ */
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void main(void);
+
+void _init(void)
+{
+ /* This function is a placeholder for the case where some more hardware
+ * specific initializations are required before jumping into the application
+ * code. You can implement it here. */
+
+ /* Jump to the application code after all initializations are completed */
+ main();
+}
+
+/* Function called after main() finishes */
+void
+_fini(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_plic.h b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..19050cf
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_plic.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V legacy RV32 soft processor PLIC access data structures and
+ * functions.
+ * Legacy RV32 soft processors are DEPRICATED.
+ * Migrate to MIV_RV32 v3.0 or later.
+ *
+ */
+#ifndef RISCV_PLIC_H
+#define RISCV_PLIC_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ External_3_IRQn = 3,
+ External_4_IRQn = 4,
+ External_5_IRQn = 5,
+ External_6_IRQn = 6,
+ External_7_IRQn = 7,
+ External_8_IRQn = 8,
+ External_9_IRQn = 9,
+ External_10_IRQn = 10,
+ External_11_IRQn = 11,
+ External_12_IRQn = 12,
+ External_13_IRQn = 13,
+ External_14_IRQn = 14,
+ External_15_IRQn = 15,
+ External_16_IRQn = 16,
+ External_17_IRQn = 17,
+ External_18_IRQn = 18,
+ External_19_IRQn = 19,
+ External_20_IRQn = 20,
+ External_21_IRQn = 21,
+ External_22_IRQn = 22,
+ External_23_IRQn = 23,
+ External_24_IRQn = 24,
+ External_25_IRQn = 25,
+ External_26_IRQn = 26,
+ External_27_IRQn = 27,
+ External_28_IRQn = 28,
+ External_29_IRQn = 29,
+ External_30_IRQn = 30,
+ External_31_IRQn = 31
+} IRQn_Type;
+
+#define EXT_INTR_SOURCES 31
+
+/*==============================================================================
+ * PLIC: Platform Level Interrupt Controller
+ */
+#define PLIC_BASE_ADDR 0x40000000UL
+
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+typedef struct
+{
+ /*-------------------- Source Priority --------------------*/
+ volatile uint32_t SOURCE_PRIORITY[1024];
+
+ /*-------------------- Pending array --------------------*/
+ volatile const uint32_t PENDING_ARRAY[32];
+ volatile uint32_t RESERVED1[992];
+
+ /*-------------------- Target enables --------------------*/
+ volatile Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ IRQ_Target_Type TARGET[15872];
+
+} PLIC_Type;
+
+#define PLIC ((PLIC_Type *)PLIC_BASE_ADDR)
+
+/*==============================================================================
+ * The function MRV_PLIC_init() initializes the PLIC controller and enables
+ * the global external interrupt bit.
+ */
+static inline void MRV_PLIC_init(void)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* Disable all interrupts for the current hart. */
+ for(inc = 0; inc < ((EXT_INTR_SOURCES + 32u) / 32u); ++inc)
+ {
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;
+ }
+
+ /* Set priorities to zero. */
+ for(inc = 0; inc < EXT_INTR_SOURCES; ++inc)
+ {
+ PLIC->SOURCE_PRIORITY[inc] = 0;
+ }
+
+ /* Set the threshold to zero. */
+ PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;
+
+ /* Enable machine external interrupts. */
+ set_csr(mie, MIP_MEIP);
+}
+
+/*==============================================================================
+ * The function MRV_PLIC_enable_irq() enables the external interrupt for the
+ * interrupt number indicated by the parameter IRQn.
+ */
+static inline void MRV_PLIC_enable_irq(IRQn_Type IRQn)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
+ current |= (uint32_t)1 << (IRQn % 32);
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
+}
+
+/*==============================================================================
+ * The function MRV_PLIC_disable_irq() disables the external interrupt for
+ * the interrupt number indicated by the parameter IRQn.
+
+ * NOTE:
+ * This function can be used to disable the external interrupt from outside
+ * external interrupt handler function.
+ * This function MUST NOT be used from within the External Interrupt handler.
+ * If you wish to disable the external interrupt while the interrupt handler
+ * for that external interrupt is executing then you must use the return value
+ * EXT_IRQ_DISABLE to return from the extern interrupt handler.
+ */
+static inline void MRV_PLIC_disable_irq(IRQn_Type IRQn)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
+}
+
+/*==============================================================================
+ * The function MRV_PLIC_set_priority() sets the priority for the external
+ * interrupt for the interrupt number indicated by the parameter IRQn.
+ */
+static inline void MRV_PLIC_set_priority(IRQn_Type IRQn, uint32_t priority)
+{
+ PLIC->SOURCE_PRIORITY[IRQn] = priority;
+}
+
+/*==============================================================================
+ * The function MRV_PLIC_get_priority() returns the priority for the external
+ * interrupt for the interrupt number indicated by the parameter IRQn.
+ */
+static inline uint32_t MRV_PLIC_get_priority(IRQn_Type IRQn)
+{
+ return PLIC->SOURCE_PRIORITY[IRQn];
+}
+
+/***************************************************************************//**
+ * MRV_PLIC_clear_pending_irq(void)
+ * This is only called by the startup hart and only once
+ * Clears any pending interrupts as PLIC can be in unknown state on startup
+ */
+static inline void MRV_PLIC_clear_pending_irq(void)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ volatile uint32_t int_num = PLIC->TARGET[hart_id].CLAIM_COMPLETE;
+ volatile int32_t wait_possible_int;
+
+ while (NoInterrupt_IRQn != int_num)
+ {
+ PLIC->TARGET[hart_id].CLAIM_COMPLETE = int_num;
+ wait_possible_int = 0xFU;
+ while (wait_possible_int)
+ {
+ wait_possible_int--;
+ }
+
+ int_num = PLIC->TARGET[hart_id].CLAIM_COMPLETE;
+ }
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_regs.h b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..1837f42
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,543 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor register bit mask and shift constants encodings.
+ *
+ */
+#ifndef RISCV_REGS_H
+#define RISCV_REGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MSTATUS_UIE 0x00000001UL
+#define MSTATUS_SIE 0x00000002UL
+#define MSTATUS_HIE 0x00000004UL
+#define MSTATUS_MIE 0x00000008UL
+#define MSTATUS_UPIE 0x00000010UL
+#define MSTATUS_SPIE 0x00000020UL
+#define MSTATUS_HPIE 0x00000040UL
+#define MSTATUS_MPIE 0x00000080UL
+#define MSTATUS_SPP 0x00000100UL
+#define MSTATUS_HPP 0x00000600UL
+#define MSTATUS_MPP 0x00001800UL
+#define MSTATUS_FS 0x00006000UL
+#define MSTATUS_XS 0x00018000UL
+#define MSTATUS_MPRV 0x00020000UL
+#define MSTATUS_SUM 0x00040000UL
+#define MSTATUS_MXR 0x00080000UL
+#define MSTATUS_TVM 0x00100000UL
+#define MSTATUS_TW 0x00200000UL
+#define MSTATUS_TSR 0x00400000UL
+#define MSTATUS_RES 0x7F800000UL
+#define MSTATUS32_SD 0x80000000UL
+#define MSTATUS64_SD 0x8000000000000000UL
+
+#define MCAUSE32_CAUSE 0x7FFFFFFFUL
+#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFFUL
+#define MCAUSE32_INT 0x80000000UL
+#define MCAUSE64_INT 0x8000000000000000UL
+
+#define MIP_SSIP (1u << IRQ_S_SOFT)
+#define MIP_HSIP (1u << IRQ_H_SOFT)
+#define MIP_MSIP (1u << IRQ_M_SOFT)
+#define MIP_STIP (1u << IRQ_S_TIMER)
+#define MIP_HTIP (1u << IRQ_H_TIMER)
+#define MIP_MTIP (1u << IRQ_M_TIMER)
+#define MIP_SEIP (1u << IRQ_S_EXT)
+#define MIP_HEIP (1u << IRQ_H_EXT)
+#define MIP_MEIP (1u << IRQ_M_EXT)
+
+#ifndef MIV_LEGACY_RV32
+#define MGEUI 16U
+#define MGECI 17U
+#define MSYS_EI0 24U
+#define MSYS_EI1 25U
+#define MSYS_EI2 26U
+#define MSYS_EI3 27U
+#define MSYS_EI4 28U
+#define MSYS_EI5 29U
+#define OPSRV_REG 30U
+
+#define MGEUI_MEIP (1u << MGEUI)
+#define MGECI_MEIP (1u << MGECI)
+#define MSYS_EI0IP (1u << MSYS_EI0)
+#define MSYS_EI1IP (1u << MSYS_EI1)
+#define MSYS_EI2IP (1u << MSYS_EI2)
+#define MSYS_EI3IP (1u << MSYS_EI3)
+#define MSYS_EI4IP (1u << MSYS_EI4)
+#define MSYS_EI5IP (1u << MSYS_EI5)
+#define MSYS_EXTERNAL_INT (0x3Fu << MSYS_EI0)
+#define MIP_OPSRV_REG (1u << OPSRV_REG)
+#endif
+
+#define PRV_M 3U
+
+#define VM_MBARE 0U
+#define VM_MBB 1U
+#define VM_MBBID 2U
+#define VM_SV32 8U
+#define VM_SV39 9U
+#define VM_SV48 10U
+
+#define IRQ_S_SOFT 1U
+#define IRQ_H_SOFT 2U
+#define IRQ_M_SOFT 3U
+#define IRQ_S_TIMER 5U
+#define IRQ_H_TIMER 6U
+#define IRQ_M_TIMER 7U
+#define IRQ_S_EXT 9U
+#define IRQ_H_EXT 10U
+#define IRQ_M_EXT 11U
+
+#define DEFAULT_RSTVEC 0x00001000
+#define DEFAULT_NMIVEC 0x00001004
+#define DEFAULT_MTVEC 0x00001010
+#define CONFIG_STRING_ADDR 0x0000100C
+#define EXT_IO_BASE 0x40000000
+#define DRAM_BASE 0x80000000
+
+#ifdef __riscv
+
+#if __riscv_xlen == 64
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
+# define MCAUSE_INT MCAUSE64_INT
+# define MCAUSE_CAUSE MCAUSE64_CAUSE
+# define RISCV_PGLEVEL_BITS 9
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+# define MCAUSE_INT MCAUSE32_INT
+# define MCAUSE_CAUSE MCAUSE32_CAUSE
+#endif
+
+#define RISCV_PGSHIFT 12U
+#define RISCV_PGSIZE (1U << RISCV_PGSHIFT)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __GNUC__
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+ __asm__ volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+ __tmp; })
+
+#define write_csr(reg, val) ({ \
+ __asm__ volatile ("csrw " #reg ", %0" :: "rK"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+ __asm__ volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
+ __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+ __asm__ volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+ __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+ __asm__ volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+ __tmp; })
+
+#ifdef __riscv_atomic
+
+#define MASK(nr) (1UL << nr)
+#define MASK_NOT(nr) (~(1UL << nr))
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically reads the value of @v.
+ */
+static inline int atomic_read(const int *v)
+{
+ return *((volatile int *)(v));
+}
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type int
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+static inline void atomic_set(int *v, int i)
+{
+ *v = i;
+}
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v.
+ */
+static inline void atomic_add(int i, int *v)
+{
+ __asm__ __volatile__ (
+ "amoadd.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (i));
+}
+
+static inline int atomic_fetch_add(unsigned int mask, int *v)
+{
+ int out;
+
+ __asm__ __volatile__ (
+ "amoadd.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_sub - subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v.
+ */
+static inline void atomic_sub(int i, int *v)
+{
+ atomic_add(-i, v);
+}
+
+static inline int atomic_fetch_sub(unsigned int mask, int *v)
+{
+ int out;
+
+ __asm__ __volatile__ (
+ "amosub.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_add_return - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v and returns the result
+ */
+static inline int atomic_add_return(int i, int *v)
+{
+ register int c;
+ __asm__ __volatile__ (
+ "amoadd.w %0, %2, %1"
+ : "=r" (c), "+A" (*v)
+ : "r" (i));
+ return (c + i);
+}
+
+/**
+ * atomic_sub_return - subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v and returns the result
+ */
+static inline int atomic_sub_return(int i, int *v)
+{
+ return atomic_add_return(-i, v);
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically increments @v by 1.
+ */
+static inline void atomic_inc(int *v)
+{
+ atomic_add(1, v);
+}
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically decrements @v by 1.
+ */
+static inline void atomic_dec(int *v)
+{
+ atomic_add(-1, v);
+}
+
+static inline int atomic_inc_return(int *v)
+{
+ return atomic_add_return(1, v);
+}
+
+static inline int atomic_dec_return(int *v)
+{
+ return atomic_sub_return(1, v);
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_sub_and_test(int i, int *v)
+{
+ return (atomic_sub_return(i, v) == 0);
+}
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type int
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_inc_and_test(int *v)
+{
+ return (atomic_inc_return(v) == 0);
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type int
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline int atomic_dec_and_test(int *v)
+{
+ return (atomic_dec_return(v) == 0);
+}
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static inline int atomic_add_negative(int i, int *v)
+{
+ return (atomic_add_return(i, v) < 0);
+}
+
+static inline int atomic_xchg(int *v, int n)
+{
+ register int c;
+ __asm__ __volatile__ (
+ "amoswap.w %0, %2, %1"
+ : "=r" (c), "+A" (*v)
+ : "r" (n));
+ return c;
+}
+
+/**
+ * atomic_and - Atomically clear bits in atomic variable
+ * @mask: Mask of the bits to be retained
+ * @v: pointer of type int
+ *
+ * Atomically retains the bits set in @mask from @v
+ */
+static inline void atomic_and(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoand.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_and(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoand.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_or - Atomically set bits in atomic variable
+ * @mask: Mask of the bits to be set
+ * @v: pointer of type int
+ *
+ * Atomically sets the bits set in @mask in @v
+ */
+static inline void atomic_or(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoor.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_or(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoor.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_xor - Atomically flips bits in atomic variable
+ * @mask: Mask of the bits to be flipped
+ * @v: pointer of type int
+ *
+ * Atomically flips the bits set in @mask in @v
+ */
+static inline void atomic_xor(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoxor.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_xor(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoxor.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long __res, __mask;
+ __mask = MASK(nr);
+ __asm__ __volatile__ ( \
+ "amoor.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long __res, __mask;
+ __mask = MASK_NOT(nr);
+ __asm__ __volatile__ ( \
+ "amoand.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+
+ unsigned long __res, __mask;
+ __mask = MASK(nr);
+ __asm__ __volatile__ ( \
+ "amoxor.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.
+ */
+
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOOR.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK(nr)));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.
+ */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOAND.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK_NOT(nr)));
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ */
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOXOR.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK(nr)));
+}
+
+#endif /* __riscv_atomic */
+
+#endif /* __GNUC__ */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __riscv */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_REGS_H */
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..7f5042b
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_stubs.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Stubs for the Mi-V soft processor Interrupt handler.
+ *
+ * The functions below will only be linked with the application code if the user
+ * does not provide an implementation for these functions. These functions are
+ * defined with weak linking so that they can be overridden by a function with
+ * same prototype in the user's application code.
+ *
+ */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__attribute__((weak)) void Software_IRQHandler(void)
+{
+ _exit(10);
+}
+
+__attribute__((weak)) void SysTick_Handler(void)
+{
+ /* Default handler */
+}
+
+#ifdef MIV_LEGACY_RV32
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t External_31_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+#else
+
+__attribute__((weak)) void External_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MGECI_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MGEUI_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void OPSRV_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..b24e729
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_syscall.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Stubs for system calls.
+ *
+ */
+#include
+#include
+#include
+#include
+#include "miv_rv32_hal.h"
+
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fabric_ip/CoreUARTapb/core_uart_apb.h"
+#else
+#include "core_uart_apb.h"
+#endif
+
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+
+/*------------------------------------------------------------------------------
+ * CoreUARTapb instance data for the CoreUARTapb instance used for standard
+ * output.
+ */
+static UART_instance_t g_stdio_uart;
+
+/*==============================================================================
+ * Flag used to indicate if the UART driver needs to be initialized.
+ */
+static int g_stdio_uart_init_done = 0;
+
+/*
+ * Disable semihosting apis
+ */
+#pragma import(__use_no_semihosting_swi)
+
+/*==============================================================================
+ * sendchar()
+ */
+int sendchar(int ch)
+{
+ /*--------------------------------------------------------------------------
+ * Initialize the UART driver if it is the first time this function is
+ * called.
+ */
+ if ( !g_stdio_uart_init_done )
+ {
+ /******************************************************************************
+ * Baud value:
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ UART_init( &g_stdio_uart,
+ MSCC_STDIO_UART_BASE_ADDR,
+ ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1),
+ (DATA_8_BITS | NO_PARITY));
+
+ g_stdio_uart_init_done = 1;
+ }
+
+ /*--------------------------------------------------------------------------
+ * Output text to the UART.
+ */
+ UART_send( &g_stdio_uart, (uint8_t *)&ch, 1 );
+
+ return (ch);
+}
+
+/*==============================================================================
+ * getachar()
+ */
+int getachar(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_byte;
+
+ if ( !g_stdio_uart_init_done )
+ {
+ /******************************************************************************
+ * Baud value:
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ UART_init( &g_stdio_uart,
+ MSCC_STDIO_UART_BASE_ADDR,
+ ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1),
+ (DATA_8_BITS | NO_PARITY));
+
+ g_stdio_uart_init_done = 1;
+ }
+
+ do
+ {
+ rx_size = UART_get_rx(&g_stdio_uart, &rx_byte, 1);
+ } while(0u == rx_size);
+
+ return rx_byte;
+}
+
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
+
+#undef errno
+static int errno;
+
+static char *__env[1] = { 0 };
+char **environ = __env;
+
+void write_hex(int fd, uint32_t hex)
+{
+ uint8_t ii;
+ uint8_t jj;
+ char towrite;
+ uint8_t digit;
+
+ write( fd , "0x", 2U );
+
+ for (ii = 8U ; ii > 0U; ii--)
+ {
+ jj = ii-1U;
+ digit = ((hex & (0xFU << (jj*4U))) >> (jj*4U));
+ towrite = digit < 0xAU ? (0x48U + digit) : (0x65U + (digit - 0xAU));
+ write( fd, &towrite, 1U);
+ }
+}
+
+
+#ifdef GDB_TESTING
+void __attribute__((optimize("O0"))) _exit(int code)
+#else
+void _exit(int code)
+#endif
+{
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+ const char * message = "\nProgam has exited with code:";
+
+ write(STDERR_FILENO, message, strlen(message));
+ write_hex(STDERR_FILENO, code);
+#endif
+
+ while (1){};
+}
+
+void *_sbrk(ptrdiff_t incr)
+{
+ extern char _end[];
+ extern char _heap_end[];
+ static char *curbrk = _end;
+ void * ret = NULL;
+
+ if (((curbrk + incr) < _end) || ((curbrk + incr) > _heap_end))
+ {
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ return(ret);
+}
+
+int _isatty(int fd)
+{
+ int ret = 0;
+
+ if (fd <= 2) /* one of stdin, stdout, stderr */
+ {
+ ret = 1;
+ }
+ else
+ {
+ errno = EBADF;
+ ret = 0;
+ }
+
+ return(ret);
+}
+
+static int stub(int err)
+{
+ errno = err;
+ return -1;
+}
+
+int _open(const char* name, int flags, int mode)
+{
+ return stub(ENOENT);
+}
+
+int _openat(int dirfd, const char* name, int flags, int mode)
+{
+ return stub(ENOENT);
+}
+
+int _close(int fd)
+{
+ return stub(EBADF);
+}
+
+int _execve(const char* name, char* const argv[], char* const env[])
+{
+ return stub(ENOMEM);
+}
+
+int _fork(void)
+{
+ return stub(EAGAIN);
+}
+
+int _fstat(int fd, struct stat *st)
+{
+ int ret = 0;
+
+ if (isatty(fd))
+ {
+ st->st_mode = S_IFCHR;
+ ret = 0;
+ }
+ else
+ {
+ ret = stub(EBADF);
+ }
+
+ return ret;
+}
+
+int _getpid(void)
+{
+ return 1;
+}
+
+int _kill(int pid, int sig)
+{
+ return stub(EINVAL);
+}
+
+int _link(const char *old_name, const char *new_name)
+{
+ return stub(EMLINK);
+}
+
+off_t _lseek(int fd, off_t ptr, int dir)
+{
+ off_t ret = 0;
+ if (_isatty(fd))
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = stub(EBADF);
+ }
+
+ return ret;
+}
+
+ssize_t _read(int fd, void* ptr, size_t len)
+{
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+
+ char* ptr1 = (char*)ptr;
+
+ if (_isatty(fd))
+ {
+ int count;
+
+ for (count = 0; count < len; count++)
+ {
+ ptr1[count] = getachar();
+ sendchar(ptr1[count]);
+
+ /* Return partial buffer if we get EOL */
+ if (('\r' == ptr1[count])||('\n' == ptr1[count]))
+ {
+ ptr1[count] = '\n';
+ return count;
+ }
+ }
+
+ return count; /* Filled the buffer */
+ }
+#endif
+
+ return stub(EBADF);
+}
+
+int _stat(const char* file, struct stat* st)
+{
+ return stub(EACCES);
+}
+
+clock_t _times(struct tms* buf)
+{
+ return stub(EACCES);
+}
+
+int _unlink(const char* name)
+{
+ return stub(ENOENT);
+}
+
+int _wait(int* status)
+{
+ return stub(ECHILD);
+}
+
+ssize_t _write(int fd, const void* ptr, size_t len)
+{
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+ int count_out;
+ char* ptr1 = (char*)ptr;
+
+ /*--------------------------------------------------------------------------
+ * Output text to the UART.
+ */
+ count_out = 0;
+ while(len--)
+ {
+ sendchar(ptr1[count_out]);
+ count_out++;
+ }
+
+ errno = 0;
+ return count_out;
+
+#else /* MSCC_STDIO_THRU_CORE_UART_APB */
+
+ return stub(EBADF);
+
+#endif /* MSCC_STDIO_THRU_CORE_UART_APB */
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/miv-rv32-udma/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/miv-rv32-udma/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/miv-rv32-udma/src/platform/miv_rv32_hal/sample_fpga_design_config.h
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file sample_fpga_design_config.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Sample design configuration settings
+ *
+ */
+ /*========================================================================*//**
+ @mainpage
+ Example file detailing how the fpga_design_config.h should be constructed
+ for the SoftConsole project targeted for Mi-V processors.
+
+ @section intro_sec Introduction
+ The SoftConsole project targeted for Mi-V processors now have an improved
+ folder structure. Detailed description of the folder structure is available
+ at https://github.com/Mi-V-Soft-RISC-V/miv-rv32-documentation.
+
+ The fpga_design_config.h must be stored as shown below
+ /boards//fpga_design_config.h
+
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.
+ In future, all the design and soft IP configurations will be automatically
+ generated from the Libero design description data.
+
+ You can use this sample file as an example.
+ Rename this file from sample_fpga_design_config.h to fpga_design_config.h
+ and then customize it per your hardware design.
+
+ @section Project configuration Instructions
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock
+ 2 Add all the soft IP core BASE addresses
+ 3. Add the peripheral Core Interrupts to Mi-V Soft processor IRQ number
+ mappings
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to
+ STDIO
+
+ **NOTE**
+ In the legacy folder structures, the file hw_config.h as was used at the
+ root of the project folder. This file is now depricated.
+
+*//*=========================================================================*/
+
+#ifndef FPGA_DESIGN_CONFIG_H_
+#define FPGA_DESIGN_CONFIG_H_
+
+/***************************************************************************//**
+ * Soft-processor clock definition
+ * This is the only clock brought over from the Mi-V Libero design.
+ */
+#ifndef SYS_CLK_FREQ
+#define SYS_CLK_FREQ 50000000UL
+#endif
+
+/***************************************************************************//**
+ * Peripheral base addresses.
+ * Format of define is:
+ * __BASE_ADDR
+ * The field is optional if there is only one instance of the core
+ * in the design
+ * MIV_ESS is an extended peripheral subsystem IP core with peripherals
+ * connections as defined below.
+ * The system can be further extended by attaching APB peripherals to the
+ * empty APB slots.
+ */
+#define MIV_ESS_PLIC_BASE_ADDR 0x70000000UL
+#define COREUARTAPB0_BASE_ADDR 0x71000000UL
+#define MIV_MTIMER_BASE_ADDR 0x72000000UL
+#define MIV_ESS_APBSLOT3_BASE_ADDR 0x73000000UL
+#define MIV_ESS_APBSLOT4_BASE_ADDR 0x74000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x75000000UL
+#define CORESPI_BASE_ADDR 0x76000000UL
+#define MIV_ESS_uDMA_BASE_ADDR 0x78000000UL
+#define MIV_ESS_WDOG_BASE_ADDR 0x79000000UL
+#define MIV_ESS_I2C_BASE_ADDR 0x7A000000UL
+#define MIV_ESS_APBSLOTB_BASE_ADDR 0x7B000000UL
+#define MIV_ESS_APBSLOTC_BASE_ADDR 0x7C000000UL
+#define MIV_ESS_APBSLOTD_BASE_ADDR 0x7D000000UL
+#define MIV_ESS_APBSLOTE_BASE_ADDR 0x7E000000UL
+#define MIV_ESS_APBSLOTF_BASE_ADDR 0x7F000000UL
+
+/***************************************************************************//**
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor
+ * interrupt in the Libero design.
+ *
+ * On the legacy RV32 cores, there can be up to 31 external interrupts (IRQ[30:0]
+ * pins). The legacy RV32 Soft processor external interrupts are defined in the
+ miv_rv32_plic.h
+ *
+ * These are of the form
+ * typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ .
+ .
+ .
+ External_31_IRQn = 31
+} IRQn_Type;
+
+ On the legacy RV32 processors, the PLIC identifies the interrupt and passes it
+ on to the processor core. The interrupt 0 is not used. The pin IRQ[0] should
+ map to External_1_IRQn likewise IRQ[30] should map to External_31_IRQn
+
+e.g
+
+#define TIMER0_IRQn External_30_IRQn
+#define TIMER1_IRQn External_31_IRQn
+
+ The MIV_RV32 soft processor has up to six optional system interrupts, MSYS_EI[n]
+ in addition to one EXT_IRQ.
+ The MIV_RV32 does not have an inbuilt PLIC and all the interrupts are directly
+ delivered to the processor core, hence unlike legacy RV32 cores, no interrupt
+ number mapping is necessary on MIV_RV32 core.
+ */
+
+/****************************************************************************
+ * Baud value to achieve a 115200 baud rate with system clock defined by
+ * SYS_CLK_FREQ.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+#define BAUD_VALUE_115200 ((SYS_CLK_FREQ / (16 * 115200)) - 1)
+
+/******************************************************************************
+ * Baud value to achieve a 57600 baud rate with system clock defined by
+ * SYS_CLK_FREQ.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ #define BAUD_VALUE_57600 ((SYS_CLK_FREQ / (16 * 57600)) - 1)
+
+/***************************************************************************//**
+ * Define MSCC_STDIO_THRU_CORE_UART_APB in the project settings if you want the
+ * standard IOs to be redirected to a terminal via UART.
+ */
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+/*
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb
+ * must be provided if it is being used
+ *
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+ */
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR
+
+#ifndef MSCC_STDIO_UART_BASE_ADDR
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+#endif
+
+#ifndef MSCC_STDIO_BAUD_VALUE
+/*
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to
+ * specify the baud value used by the standard output CoreUARTapb instance for
+ * generating the UART's baud rate if you want a different baud rate from the
+ * default of 115200 baud
+ */
+#define MSCC_STDIO_BAUD_VALUE 115200
+#endif /*MSCC_STDIO_BAUD_VALUE*/
+
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */
+/*******************************************************************************
+ * End of user edit section
+ */
+#endif /* FPGA_DESIGN_CONFIG_H_ */
diff --git a/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-execute-in-place.ld b/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..19df5fb
--- /dev/null
+++ b/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-execute-in-place.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * image executing from a one address space whereas the data, sdata and stack
+ * sections are placed in another address space. This could be used in cases such
+ * as:
+ * 1) When using MIV_RV32, the reset vector points to the LSRAM at address
+ * 0x80000000 and the data, sdata, bss and stack sections are placed in the
+ * TCM region.
+ *
+ * 2) Executing from a Non Volatile memory. The actual memory will depend on
+ * the FPGA platform. For exameple, it could be the eNVM on SmartFusion2,
+ * Igloo2 or on-board non-volatile memory which supports code execution.
+ *
+ * NOTE: Modify the memory section addresses and the sizes according to your
+ * Libero design.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x80000000, LENGTH = 16k
+ ram (rwx) : ORIGIN = 0x80004000, LENGTH = 16k
+}
+
+STACK_SIZE = 1k; /* needs to be calculated for your application */
+HEAP_SIZE = 0; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > rom
+
+ .text : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.text.entry)))
+ . = ALIGN(0x10);
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } >rom
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } >ram AT>rom
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } >ram AT>rom
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-ram.ld b/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..e0707df
--- /dev/null
+++ b/miv-rv32-udma/src/platform/platform_config_reference/linker/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019-2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * file name : miv-rv32-ram.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * debug image executing in SRAM.
+ *
+ * This linker script assumes that a RAM is connected at on Mi-V soft processor
+ * memory space pointed by the reset vector address.
+ *
+ * NOTE : Modify the memory section address and the size according to your
+ * Libero design.
+ * For example:
+ * 1) If you want to download and step debug at a different RAM memory address in
+ * your design (For example TCM base address) than the one provided in this file.
+ * 2) The MIV_RV32, when used with MIV_ESS IP, provides ways to copy the executable
+ * HEX file from external Non-Volatile memory into the TCM at reset. In this
+ * case your executable must be linked to the TCM address.
+ *
+ * To know more about the memory map of the MIV_RV32 based Libero design, open
+ * the MIV_RV32 IP configurator and look for "Reset Vector Address" and the
+ * "Memory Map" tab.
+ *
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 32k
+}
+
+STACK_SIZE = 2k; /* needs to be calculated for your application */
+HEAP_SIZE = 0k; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .entry : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.entry)))
+ . = ALIGN(0x10);
+ } > ram
+
+ .text : ALIGN(0x10)
+ {
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } > ram
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } > ram
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } > ram
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/miv-rv32-udma/src/platform/platform_config_reference/linker/readme.md b/miv-rv32-udma/src/platform/platform_config_reference/linker/readme.md
new file mode 100644
index 0000000..5581d1b
--- /dev/null
+++ b/miv-rv32-udma/src/platform/platform_config_reference/linker/readme.md
@@ -0,0 +1,2 @@
+# readme
+
diff --git a/miv-rv32-udma/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md b/miv-rv32-udma/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md
new file mode 100644
index 0000000..5581d1b
--- /dev/null
+++ b/miv-rv32-udma/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md
@@ -0,0 +1,2 @@
+# readme
+