diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/.cproject b/driver-examples/miv-watchdog/miv-rv32-wdog/.cproject
new file mode 100644
index 0000000..1469831
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/.cproject
@@ -0,0 +1,622 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/.gitignore b/driver-examples/miv-watchdog/miv-rv32-wdog/.gitignore
new file mode 100644
index 0000000..01bd439
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/.gitignore
@@ -0,0 +1,5 @@
+/.settings/
+/Debug/
+/Release/
+/miv32imc-Debug/
+/miv32imc-Release/
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/.project b/driver-examples/miv-watchdog/miv-rv32-wdog/.project
new file mode 100644
index 0000000..85bcd65
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/.project
@@ -0,0 +1,36 @@
+
+
+ miv-rv32-wdog
+
+
+
+
+
+ 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
+
+
+
+ PLATFORM_LOC
+ $%7BPARENT-1-PROJECT_LOC%7D/platform
+
+
+ PLATFORM_LOC1
+ $%7BPARENT-3-ECLIPSE_HOME%7D/BB5/g/new/mss-i2c-examples/myprojects/miv_rv32/platform
+
+
+
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/README.md b/driver-examples/miv-watchdog/miv-rv32-wdog/README.md
new file mode 100644
index 0000000..b5f48fb
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/README.md
@@ -0,0 +1,57 @@
+# MIV Watchdog Example
+
+This project demonstrates the Mi-V Soft IP WDOG module functionality, which is delivered as a
+part of MIV Extended Sub System(MIV_ESS).
+This project will perform the watchdog configurations, the time-out interrupt and the
+Maximum Value up to which Refresh is Permitted (MVRP) interrupt and their handling.
+
+The MIV ESS Core generates MVRP_IRQ and WDOG_IRQ interrupts which can be connected
+to any of the external interrupt pins on the MIV_RV32. The application developer
+will have to handle these interrupts in the respective interrupt handlers.
+
+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 interface1 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 with MIV_RV32 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/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw attach.launch b/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw attach.launch
new file mode 100644
index 0000000..5558a29
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw attach.launch
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw debug.launch b/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw debug.launch
new file mode 100644
index 0000000..1945fac
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/miv-rv32-wdog hw debug.launch
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/application/main.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/application/main.c
new file mode 100644
index 0000000..bebe4da
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/application/main.c
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Sample project to demonstrate the MIV Watchdog functionality.
+ *
+ * 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_watchdog/miv_watchdog.h"
+
+/******************************************************************************
+ * MIV Peripheral instance data.
+ *****************************************************************************/
+ UART_instance_t g_uart;
+ miv_wdog_config_t wd0_config;
+
+/*-----------------------------------------------------------------------------
+ * Watchdog instance data.
+ */
+volatile uint8_t h0_triggered = 0u;
+volatile uint8_t h0_mvrp = 0u;
+
+/*==============================================================================
+ * Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n***********************************************************************\r\n\n\
+******************** Mi-V Watchdog Example ***********************\r\n\n\
+***************************************************************************\r\n\r\n\
+The MVRP interrupt will occur after 34 seconds, after system reset \r\n\
+The Time out interrupt will occur after 85 seconds, after system reset \r\n\n ";
+
+const uint8_t g_separator[] =
+"\r\n----------------------------------------------------------------------\r\n";
+
+static void display_greeting(void);
+
+uint8_t data_buffer [1024];
+uint8_t input_text[506] = {0x00};
+
+static void clear_data_buffer(void)
+{
+ uint32_t idx = 0u;
+
+ while (idx < 1024u)
+ {
+ data_buffer[idx++] = 0x00u;
+ }
+}
+/*==============================================================================
+ * Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_polled_tx_string(&g_uart, g_greeting_msg);
+}
+
+void MSYS_EI3_IRQHandler()
+{
+ h0_mvrp = 1;
+
+ /* Un-commenting the below statement will refresh the Watchdog and then the
+ * timer will be reloaded to original TIME value and start decrementing.
+ * This will avoid the timeout interrupt and RESET.
+ *
+ * Not reloading the Watchdog will make the down counter to pass below
+ * trigger value and cause a timeout interrupt. When the down counter rolls
+ * down to zero, it would generate a RESET.
+ * */
+
+// MIV_WDOG_reload();
+
+ MIV_WDOG_clear_mvrp_irq();
+
+}
+
+void MSYS_EI4_IRQHandler()
+{
+ h0_triggered = 1u;
+
+ MIV_WDOG_clear_timeout_irq();
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+void main(void)
+{
+ size_t rx_size;
+ uint8_t rx_buff[1] = {0x00};
+ uint32_t counter = 0;
+ uint32_t read_data[100] = {0};
+ uint32_t icount = 0u;
+ uint32_t current_value = 0u;
+
+ clear_data_buffer();
+
+ /* 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_EIE3_IRQn | MRV32_MSYS_EIE4_IRQn );
+
+ HAL_enable_interrupts();
+
+ MIV_WDOG_init(MIV_ESS_WDOG_BASE_ADDR);
+ /* Read the default config */
+ MIV_WDOG_get_config(&wd0_config);
+
+ /* Set such that the MVRP interrupt will happen after ~13 seconds after
+ * reset and the Trigger interrupt will happen after ~25 seconds.
+ */
+
+ wd0_config.forbidden_en = MIV_WDOG_ENABLE;
+ wd0_config.timeout_val = 0x3e0u;
+ wd0_config.mvrp_val = (10000000UL);
+ wd0_config.time_val = (2UL*10000000UL);
+
+ MIV_WDOG_configure(&wd0_config);
+
+ MIV_WDOG_enable_mvrp_irq();
+
+ while(1u)
+ {
+ icount++;
+
+ if (0x90000u == icount)
+ {
+ /*
+ * Read the current value after 90000 ticks.
+ */
+ icount = 0u;
+ current_value = MIV_WDOG_current_value();
+ snprintf((char *)data_buffer, sizeof(data_buffer),
+ "WD0 value = %x\r\n", *(uint32_t*)0x79000000);
+
+
+ UART_polled_tx_string(&g_uart,
+ data_buffer);
+ }
+
+ if(h0_mvrp)
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\nMVRP Interrupt...\n");
+ h0_mvrp = 0;
+
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\nMVRP IRQ Cleared \r\n");
+
+ snprintf((char *)data_buffer, sizeof(data_buffer),
+ "\r\nH0 MVRP - Returned to Local\r\n\n");
+
+ UART_polled_tx_string(&g_uart,
+ data_buffer);
+ }
+
+ if(h0_triggered)
+ {
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\nWDOG Interrupt...\n");
+
+ h0_triggered = 0;
+
+ UART_polled_tx_string(&g_uart,
+ (const uint8_t *)"\r\nWDOG IRQ Cleared \r\n");
+
+ snprintf((char *)data_buffer, sizeof(data_buffer),
+ "\r\nH0 timeout - Returned to Local\r\n");
+
+
+ UART_polled_tx_string(&g_uart,
+ data_buffer);
+ }
+
+ }
+}
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/fpga_design/design_description/README.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/fpga_design/design_description/README.md
new file mode 100644
index 0000000..4f7aa4b
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..cd52abc
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * 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_WDOG_BASE_ADDR 0x79000000UL
+
+/***************************************************************************//**
+ * 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/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-execute-in-place.ld b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..19df5fb
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..e0707df
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/miv_rv32_hal_config/readme.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/boards/polarfire-eval-kit/platform_config/miv_rv32_hal_config/readme.md
new file mode 100644
index 0000000..46ee0bd
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/middleware/README.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/middleware/README.md
new file mode 100644
index 0000000..dafa1d2
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/middleware/README.md
@@ -0,0 +1 @@
+Place holder readme file in the middleware directory.
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..63cd377
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..3491d68
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..0c13e28
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..2b2087a
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..2ce0b88
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..8651f0c
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..5cf19c5
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V Watchdog Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_watchdog.h file for more information.
+ */
+
+#include "miv_watchdog.h"
+
+addr_t g_this_wdog;
+
+/***************************************************************************//*
+ * Please refer to miv_watchdog.h for more info about this function
+ */
+void
+MIV_WDOG_init
+(
+ addr_t base_addr
+)
+{
+ /* Register the Mi-V Watchdog base address to the driver */
+ g_this_wdog = base_addr;
+}
+
+/***************************************************************************//*
+ * Please refer to miv_watchdog.h for more info about this function
+ */
+uint8_t MIV_WDOG_configure
+(
+ const miv_wdog_config_t *config
+)
+{
+ uint8_t error = 0u;
+
+ /* check load value and trigger max value */
+ if (config->timeout_val <= MIV_WDOG_TRIGGER_MAX)
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGTRIG,(config->timeout_val));
+ }
+ else
+ {
+ error = 1u;
+ }
+
+ if (config->time_val <= MIV_WDOG_TIMER_MAX)
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGMSVP,(config->mvrp_val));
+ }
+ else
+ {
+ error = 1u;
+ }
+
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGCNTL_NEXT_ENFORBIDDEN,
+ config->forbidden_en);
+
+ /* Reload watchdog with new load if it is not in forbidden window */
+ if (!(WDOGSTAT_FORBIDDEN_MASK & (HAL_get_32bit_reg(g_this_wdog, WDOGSTAT))))
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGRFSH, MIV_WDOG_REFRESH_KEY);
+ }
+ else
+ {
+ error = 1u;
+ }
+
+ return (error);
+}
+
+/***************************************************************************//*
+ * Please refer to miv_watchdog.h for more info about this function
+ */
+void MIV_WDOG_get_config
+(
+ miv_wdog_config_t *config
+)
+{
+ if (0 != g_this_wdog)
+ {
+
+ config->time_val = HAL_get_32bit_reg(g_this_wdog, WDOGTIME);
+
+ config->timeout_val = HAL_get_32bit_reg(g_this_wdog, WDOGTRIG);
+
+ config->mvrp_val = HAL_get_32bit_reg(g_this_wdog, WDOGMSVP);
+
+ config->forbidden_en = HAL_get_32bit_reg_field(g_this_wdog,
+ WDOGCNTL_NEXT_ENFORBIDDEN);
+ }
+}
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
@@ -0,0 +1,553 @@
+/*******************************************************************************
+ * 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
+ * Watchdog module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+/*=========================================================================*//**
+ @mainpage MiV Watchdog Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V Watchdog module in the MIV_ESS is used to generate a reset for the
+ system automatically if the software doesn't periodically update or refresh
+ the timer countdown register. This software driver provides set of functions
+ for controlling Mi-V Watchdog module as a part of bare metal system where no
+ operating system is available. The driver can be adapted for use as a 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 the
+ driver.
+
+ Mi-V Watchdog provides following features:
+ - Initializing the Mi-V Watchdog
+ - Reading current value and status of watchdog timer
+ - Refreshing the watchdog timer value
+ - Enabling, disabling and clearing timeout and Maximum Value up to which
+ Refresh is Permitted (MVRP) interrupts.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V Watchdog
+ module the the call to the MIV_WDOG_init() and MIV_WDOG_configure() functions.
+
+ No MIV_WDOG hardware configuration parameter are used by the driver, apart
+ from the MIV_WDOG base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V Watchdog driver functions are grouped into the following categories:
+ - Initialization and configuration
+ - Reading the current value and status of the watchdog timer
+ - Refreshing the watchdog timer value
+ - Support for enabling, disabling and clearing time-out and MVRP interrupts.
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The MIV_WDOG_init() function stores the base of MIV_WDT module in the MIV_ESS.
+ This base address is used by rest of the functions to access the Mi-V Watchdog
+ registers. Please make call this function before calling any other function
+ from this driver.
+ Note: The Mi-V Watchdog driver supports only one instance of MIV_WDT in the
+ hardware.
+ The Mi-V Watchdog driver provides the MIV_WDOG_configure() function to
+ configure the MIV_WDOG module with desired configuration values. It also
+ provides the MIV_WDOG_get_config() to read back the current configuration of
+ the MIV_WDOG. You can use this function to retrieve the current configurations
+ and then overwrite them with the application specific values, such as initial
+ watchdog timer value, Maximum Value (up to which) Refresh (is) Permitted,
+ watchdog time-out value, enable/disable forbidden region, enable/disable
+ MVRP interrupt and interrupt type.
+
+ --------------------------------------------
+ Reading the Watchdog Timer Value and Status
+ --------------------------------------------
+ Mi-V Watchdog is a down counter. A refresh forbidden window can be created by
+ configuring the watchdog Maximum Value up to which Refresh is Permitted (MVRP).
+ When the current value of the watchdog timer is greater than the MVRP value,
+ refreshing the watchdog is forbidden. Attempting to refresh the watchdog timer
+ in the forbidden window will assert a timeout interrupt. The
+ MIV_WDOG_forbidden_status() function can be used to know whether the watchdog
+ timer is in forbidden window or has crossed it. By default, the forbidden
+ window is disabled. It can be enabled by providing an appropriate value as
+ parameter to the MIV_WDOG_configure() function. When the forbidden window is
+ disabled, any attempt to refresh the watchdog timer is ignored and the counter
+ keeps on down counting.
+
+ The current value of the watchdog timer can be read using the
+ MIV_WDOG_current_value() function. This function can be called at any time.
+
+ --------------------------------------------
+ Refreshing the Watchdog Timer Value
+ --------------------------------------------
+ The watchdog timer value is refreshed using the MIV_WDOG_reload() function.
+ The value reloaded into the watchdog timer down-counter is specified at the
+ configuration time with an appropriate value as parameter to the
+ MIV_WDOG_get_config() function.
+
+ --------------------------------------------
+ Interrupt Control
+ --------------------------------------------
+ The Mi-V Watchdog generates two interrupts, The MVRP interrupt and
+ the timeout interrupt.
+ The MVRP interrupt is generated when the watchdog down-counter crosses the
+ Maximum Value up to which Refresh is Permitted (MVRP). Following functions to
+ control MVRP interrupt:
+ - MIV_WDOG_enable_mvrp_irq
+ - MIV_WDOG_disable_mvrp_irq
+ - MIV_WDOG_clear_mvrp_irq
+
+ The timeout interrupt is generated when the watchdog down-counter crosses the
+ watchdog timeout value. The timeout value is a non-zero value and it can be
+ set to a maximum of MIV_WDOG_TRIGGER_MAX. The non-maskable interrupt is
+ generated when the watchdog crosses this timeout value, the down counter
+ keeps on down counting and a reset signal is generated when reaches zero.
+ Following functions to control timeout interrupt:
+ - MIV_WDOG_enable_timeout_irq
+ - MIV_WDOG_disable_timeout_irq
+ - MIV_WDOG_clear_timeout_irq
+
+*//*=========================================================================*/
+
+#ifndef MIV_WATCHDOG_H_
+#define MIV_WATCHDOG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_watchdog_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/****************************************************************************//*
+ * The following constants can be used to configure the Mi-V Watchdog where a
+ * zero or non-zero value such as enable or disable is to be provided as a input
+ * parameter as shown below:
+ */
+#define MIV_WDOG_ENABLE 1u
+#define MIV_WDOG_DISABLE 0u
+
+/***************************************************************************//**
+ The miv_wdog_config_t type for the watchdog Configuration structure. This
+ type is used as a parameter for the MIV_WDOG_configure() and the
+ MIV_WDOG_get_config() functions.
+
+ Following are the values as part of this structure
+| Parameter | Description |
+|------------------|-----------------------------------------------------------|
+| time_val | The value from which the watchdog timer counts down |
+| mvrp_val | The Watchdog MVRP value |
+| timeout_val | The watchdog timeout value |
+| forbidden_en | Enable/disable the forbidden window |
+| | When set, if a refresh occurs in the forbidden window, |
+| | the watchdog timeout interrupt will be generated. |
+
+Time calculation example:
+
+ time_val = 0xFFFFF0u
+ mvrp_val = 0x989680u
+ timeout_val = 0x3e8u
+
+ A prescaler = 256 is used.
+ Considering clock = 50Mhz
+
+ The MVRP interrupt will happen after
+ (0xFFFFF0 - 0x989680) * ( 1/(50MHz/256))
+ mvrp interrupt will happen after 34 sec. after system reset
+
+ (0xFFFFF0 - 0x3e8) * ( 1/(50MHz/256))
+ timeout interrupt will happen after 85 sec. after system reset
+ */
+typedef struct miv_wdog_config
+{
+ uint32_t time_val;
+ uint32_t mvrp_val;
+ uint32_t timeout_val;
+ uint32_t forbidden_en;
+ uint32_t intr_type;
+}miv_wdog_config_t;
+
+extern addr_t g_this_wdog;
+
+/***************************************************************************//*
+ Internal constants and types
+*******************************************************************************/
+
+/// @cond private
+#define MIV_WDOG_TRIGGER_MAX 4095u
+#define MIV_WDOG_TIMER_MAX 16777200u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//*
+MIV_WDOG_REFRESH_KEY
+=====================
+
+The MIV_WDOG_REFRESH_KEY macro holds the magic value which will cause a
+reload of the watchdog's down counter when written to the watchdog's
+WDOGREFRESH register.
+*/
+#define MIV_WDOG_REFRESH_KEY (uint32_t)0xDEADC0DEU
+
+/*-------------------------------------------------------------------------*//*
+MIV_WDOG_FORCE_RESET_KEY
+=====================
+The MIV_WDOG_FORCE_RESET_KEY macro holds the magic value which will force a
+reset if the watchdog is already timeout. Writing any other value or writing
+TRIGGER register at other times will trigger the watchdog NMI sequence
+(i.e raise a timeout interrupt)
+ */
+#define MIV_WDOG_FORCE_RESET_KEY (uint32_t)0xDEADU
+
+/***************************************************************************//**
+ * The MIV_WDOG_init() is used to register the Mi-V Watchdog module base
+ * address to the driver.
+ *
+ * Note: User should call this function before calling any other Mi-V watchdog
+ * driver function.
+ *
+ * @param base_addr
+ * The base address of the Mi-V watchdog module. This address is used by
+ * rest of the watchdog driver functions to access the registers.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_WDOG_init
+(
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_WDOG_get_config() function returns the current configurations of the
+ * Mi-V Watchdog. The Mi-V Watchdog is pre-initialized by the flash
+ * bits at the design time. When used for the first time before calling the
+ * MIV_WDOG_configure() function, this function will return the default
+ * configurations as configured at the design time.
+ *
+ * @param config
+ * The config parameter is used to store the current configuration of the Mi-V
+ * Watchdog.
+ *
+ * Please see the description of miv_wdog_config_t for details.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ */
+void
+MIV_WDOG_get_config
+(
+ miv_wdog_config_t* config
+);
+
+/***************************************************************************//**
+ * The MIV_WDOG_configure() function configures the watchdog module. The
+ * Watchdog module is pre-initialized by the flash bits at the design time to the
+ * default values. You can reconfigure the Watchdog module using
+ * MIV_WDOG_configure() function.
+ *
+ * Note that the MIV_WDOG_configure() function can be used only once, as it
+ * writes into the TIME register. After a write into the TIME register, the TIME,
+ * TRIGGER and MSVP register values are frozen and can't be altered again unless
+ * a system reset happens.
+ *
+ * Note also that the Mi-V Watchdog is not enabled at reset, calling this function
+ * will start the watchdog, it cannot then be disabled and must be refreshed
+ * periodically.
+ *
+ * @param config
+ * The config parameter is the input parameter in which the configurations to
+ * be applied to the watchdog module are provided by the application.
+ * Please see the description of miv_wdog_config_t for details.
+ *
+ * @return
+ * This function returns a zero value when executed successfully. A non-zero
+ * value is returned when the configuration values are out of bound.
+ *
+ * Example:
+ */
+uint8_t
+MIV_WDOG_configure
+(
+ const miv_wdog_config_t * config
+);
+
+/***************************************************************************//**
+ * The MIV_WDOG_reload() function causes the watchdog to reload its down-counter
+ * timer with the load value configured through interrupt handler. This function
+ * must be called regularly to avoid a system reset or a watchdog interrupt.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return a value.
+ */
+static inline void
+MIV_WDOG_reload
+(
+ void
+)
+{
+ if (0 != g_this_wdog)
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGRFSH, MIV_WDOG_REFRESH_KEY);
+ }
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_current_value() function returns the current value of the
+ * watchdog's down-counter.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function returns the current value of the watchdog’s down-counter as
+ * a 32-bit unsigned integer.
+ */
+static inline uint32_t
+MIV_WDOG_current_value
+(
+ void
+)
+{
+ return (HAL_get_32bit_reg(g_this_wdog, WDOGRFSH));
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_forbidden_status() function returns the refresh status of the
+ * Mi-V Watchdog.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function returns the refresh status of the watchdog. A value of 1
+ * indicates that watchdog's down-counter is within the forbidden window and
+ * that a reload should not be done. A value of 0 indicates that the watchdog's
+ * down counter is within the permitted window and that a reload is allowed.
+ */
+static inline uint32_t
+MIV_WDOG_forbidden_status
+(
+ void
+)
+{
+ return (HAL_get_32bit_reg_field(g_this_wdog, WDOGSTAT_FORBIDDEN));
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_enable_mvrp_irq() function enables the MVRP interrupt.
+ * This interrupt is asserted when the timer countdown register leaves the
+ * maximum value up to which refresh is permitted (MVRP) window.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return a value.
+ *
+ * Example:
+ */
+static inline void
+MIV_WDOG_enable_mvrp_irq
+(
+ void
+)
+{
+
+ if (0 != g_this_wdog)
+ {
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGCNTL_NEXT_INTENT_MSVP, 0x01u);
+ }
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_disable_mvrp_irq() function disables the generation of the
+ * MVRP interrupt.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return a value.
+ */
+static inline void
+MIV_WDOG_disable_mvrp_irq
+(
+ void
+)
+{
+ if (0 != g_this_wdog)
+ {
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGCNTL_NEXT_INTENT_MSVP, 0x0u);
+ }
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_clear_timeout_irq() function clears the watchdog’s timeout
+ * interrupt which is connected to the MIV-RV32 interrupt. Calling
+ * MIV_WDOG_clear_timeout_irq() results in clearing the MIV-RV32 interrupt.
+ * Note: You must call the MIV_WDOG_clear_timeout_irq() function as part of your
+ * implementation of the interrupt handler in order to prevent the same
+ * interrupt event re-triggering a call to the timeout ISR.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return any value.
+ *
+ */
+static inline void
+MIV_WDOG_clear_timeout_irq
+(
+ void
+)
+{
+ if (0 != g_this_wdog)
+ {
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGSTAT_WDOG_TRIPPED, 0x01u);
+ /*
+ * Perform a second write to ensure that the first write completed before
+ * returning from this function. This is to account for posted writes across
+ * the AHB matrix. The second write ensures that the first write has
+ * completed and that the interrupt line has been de-asserted by the time
+ * the function returns. Omitting the second write may result in a delay
+ * in the de-assertion of the interrupt line going to the RISC-V and a
+ * retriggering of the interrupt.
+ */
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGSTAT_WDOG_TRIPPED, 0x01u);
+ }
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_clear_mvrp_irq() function clears the mvrp interrupt.
+ *
+ * Note: You must call the MIV_WDOG_clear_mvrp_irq() function as part of your
+ * implementation of the interrupt service routine (ISR) in order to
+ * prevent the same interrupt event re-triggering a call to the mvrp ISR.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return a value.
+ */
+static inline void
+MIV_WDOG_clear_mvrp_irq
+(
+ void
+)
+{
+ if (0 != g_this_wdog)
+ {
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGSTAT_MSVP_TRIPPED, 0x01u);
+ /*
+ * Perform a second write to ensure that the first write completed before
+ * returning from this function. This is to account for posted writes across
+ * the AHB matrix. The second write ensures that the first write has
+ * completed and that the interrupt line has been de-asserted by the time
+ * the function returns. Omitting the second write may result in a delay
+ * in the de-assertion of the interrupt line going to the RISC-V and a
+ * re-triggering of the interrupt.
+ */
+ HAL_set_32bit_reg_field(g_this_wdog, WDOGSTAT_MSVP_TRIPPED, 0x01u);
+ }
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_timeout_occured() function reports the occurrence of a timeout
+ * event.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * A zero value indicates no watchdog timeout event occurred. A value of 1
+ * indicates that a timeout event occurred.
+ */
+static inline uint32_t
+MIV_WDOG_timeout_occured
+(
+ void
+)
+{
+ return (HAL_get_32bit_reg_field(g_this_wdog, WDOGSTAT_TRIGGERED));
+}
+
+/***************************************************************************//**
+ * The MIV_WDOG_force_reset() function is used to force an immediate reset
+ * if the watchdog has already triggered. Writing any value in this condition
+ * will result in watchdog timeout.
+ * The time out interrupt WDOG_IRQ will be set to high and watchdog timer
+ * countdown register updated with watchdog trigger timeout register value.
+ * If the Watchdog has timed out, a special 16-bit value needs to be written
+ * to the register to force a reset on CPU_RESETN, 0xDEAD
+ * Then the Watchdog countdown is reset/updated with the top Watchdog Runtime
+ * register value.
+ *
+ * @param
+ * Void
+ *
+ * @return
+ * This function does not return a value.
+ */
+static inline void
+MIV_WDOG_force_reset
+(
+ void
+)
+{
+ if (WDOGSTAT_TRIGGERED_MASK ==
+ HAL_get_32bit_reg_field(g_this_wdog, WDOGSTAT_TRIGGERED))
+
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGFORCE, MIV_WDOG_FORCE_RESET_KEY);
+ }
+
+ else
+ {
+ HAL_set_32bit_reg(g_this_wdog, WDOGFORCE, 0x0u);
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_WATCHDOG_H_ */
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
@@ -0,0 +1,122 @@
+ /*******************************************************************************
+ * 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 watchdog module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_WDOG_REGISTERS
+#define MIV_WDOG_REGISTERS 1u
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Refresh register details
+ */
+#define WDOGRFSH_REG_OFFSET 0x00u
+
+/* Refresh register bits */
+#define WDOGRFSH_OFFSET 0x00u
+#define WDOGRFSH_MASK 0xFFFFFFFFu
+#define WDOGRFSH_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define WDOGCNTL_REG_OFFSET 0x04u
+
+/* Control register next intent msvp bit */
+#define WDOGCNTL_NEXT_INTENT_MSVP_OFFSET 0x04u
+#define WDOGCNTL_NEXT_INTENT_MSVP_MASK 0x01u
+#define WDOGCNTL_NEXT_INTENT_MSVP_SHIFT 0u
+
+/* Control register next intent wdog bit */
+#define WDOGCNTL_NEXT_INTENT_WDOG_OFFSET 0x04u
+#define WDOGCNTL_NEXT_INTENT_WDOG_MASK 0x02u
+#define WDOGCNTL_NEXT_INTENT_WDOG_SHIFT 1u
+
+/* Control register next enforbidden bit */
+#define WDOGCNTL_NEXT_ENFORBIDDEN_OFFSET 0x04u
+#define WDOGCNTL_NEXT_ENFORBIDDEN_MASK 0x10u
+#define WDOGCNTL_NEXT_ENFORBIDDEN_SHIFT 4u
+
+/*------------------------------------------------------------------------------
+ * Watchdog status register
+ */
+#define WDOGSTAT_REG_OFFSET 0x08u
+
+/* msvp_tripped bit */
+#define WDOGSTAT_MSVP_TRIPPED_OFFSET 0x08u
+#define WDOGSTAT_MSVP_TRIPPED_MASK 0x01u
+#define WDOGSTAT_MSVP_TRIPPED_SHIFT 0u
+
+/* WDOG Tripped bit */
+#define WDOGSTAT_WDOG_TRIPPED_OFFSET 0x08u
+#define WDOGSTAT_WDOG_TRIPPED_MASK 0x02u
+#define WDOGSTAT_WDOG_TRIPPED_SHIFT 1u
+
+/* Forbidden bit */
+#define WDOGSTAT_FORBIDDEN_OFFSET 0x08u
+#define WDOGSTAT_FORBIDDEN_MASK 0x04u
+#define WDOGSTAT_FORBIDDEN_SHIFT 2u
+
+/* Triggered bit */
+#define WDOGSTAT_TRIGGERED_OFFSET 0x08u
+#define WDOGSTAT_TRIGGERED_MASK 0x08u
+#define WDOGSTAT_TRIGGERED_SHIFT 3u
+
+/* wdoglocked bit */
+#define WDOGSTAT_WDOGLOCKED_OFFSET 0x08u
+#define WDOGSTAT_WDOGLOCKED_MASK 0x10u
+#define WDOGSTAT_WDOGLOCKED_SHIFT 4u
+
+/*------------------------------------------------------------------------------
+ * Watchdog runtime register
+ */
+#define WDOGTIME_REG_OFFSET 0x0Cu
+
+/* wdogmsvp bit */
+#define WDOGTIME_WDOGVALUE_OFFSET 0x0Cu
+#define WDOGTIME_WDOGVALUE_MASK 0xFFFFFFu
+#define WDOGTIME_WDOGVALUE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Watchdog MVRP register
+ */
+#define WDOGMSVP_REG_OFFSET 0x10u
+
+/* wdogmsvp bit */
+#define WDOGMSVP_OFFSET 0x10u
+#define WDOGMSVP_MASK 0xFFFFFFu
+#define WDOGMSVP_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Watchdog Trigger Timeout register
+ */
+#define WDOGTRIG_REG_OFFSET 0x14u
+
+/* wdogmsvp bit */
+#define WDOGTRIG_WDOGRST_OFFSET 0x14u
+#define WDOGTRIG_WDOGRST_MASK 0xFFFFFFu
+#define WDOGTRIG_WDOGRST_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Watchdog Force Reset register details
+ */
+#define WDOGFORCE_REG_OFFSET 0x18u
+
+/* Refresh register bits */
+#define WDOGFORCE_OFFSET 0x18u
+#define WDOGFORCE_MASK 0xFFFFFFFFu
+#define WDOGFORCE_SHIFT 0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_WATCHDOG_REGS_H_ */
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/cpu_types.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal_assert.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..8e0c747
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal_irq.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..6fe7fce
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_macros.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..ed2c681
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_reg_access.S b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..f4aa0a0
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_reg_access.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1f6a551
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/readme.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/hal/readme.md
new file mode 100644
index 0000000..c756b34
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..19df5fb
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..e0707df
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_entry.S b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..a19a813
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_hal.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..8fa82b1
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_hal.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..7231610
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_init.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..e5f811f
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_plic.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..19050cf
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_regs.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..1837f42
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..7f5042b
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..b24e729
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/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/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/linker/readme.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/linker/readme.md
new file mode 100644
index 0000000..5581d1b
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/linker/readme.md
@@ -0,0 +1,2 @@
+# readme
+
diff --git a/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md
new file mode 100644
index 0000000..5581d1b
--- /dev/null
+++ b/driver-examples/miv-watchdog/miv-rv32-wdog/src/platform/platform_config_reference/miv_rv32_hal_config/readme.md
@@ -0,0 +1,2 @@
+# readme
+